[JSOI2012][bzoj4332] 分零食 [FFT]
题面
思路
首先,这个数据如果没有这么大,我们还是可以做朋友的......
设$dp\left[i\right]\left[j\right]$代表前j个零食分给了前i个人的方案数
那么dp方程显然:
$dp\left[i\right]\left[j\right]=\sum_{k=1}^{j-1} dp\left[i-1\right]\left[k\right]+f\left(j-k\right)$
其中$f\left(x\right)$就是题目里给的那个二次函数
同时有一个性质:
$dp\left[i\right]\left[j\right]=dp\left[\frac i2\right]\left[k\right]\ast dp\left[\frac i2\right]\left[j-k\right]$
显然这道题不能直接O(nm)递推......那我们换个办法来想
n辣么大,为什么我们不考虑 一下用倍增的方法呢?正好上面那个性质可以利用一下
并且还应当注意,我们最后要求的是$\sum_{i=1}^n dp\left[i\right]\left[m\right]$
所以我们设$p\left[i\right]\left[j\right]=\sum_{k=1}^n dp\left[k\right]\left[j\right]$
$p\left[i\right]\left[j\right]=p\left[\frac i2\right]\left[j\right]+\sum_{k=1}^{\frac i2}dp\left[k+\frac i2\right]\left[j\right]$
$p\left[i\right]\left[j\right]=p\left[\frac i2\right]\left[j\right]+\sum_{k=1}^{\frac i2}\sum_{l=1}^{j-1}dp\left[k\right]\left[l\right]dp\left[\frac i2\right]\left[j-l\right]$
$p\left[i\right]\left[j\right]=p\left[\frac i2\right]\left[j\right]+\sum_{l=1}{j-1}\sum_{k=1}{\frac i2}dp\left[k\right]\left[l\right]dp\left[\frac i2\right]\left[j-l\right]$
$p\left[i\right]\left[j\right]=p\left[\frac i2\right]\left[j\right]+\sum_{l=1}^{j-1}dp\left[\frac i2\right]\left[j-l\right]\sum_{k=1}^{\frac i2}dp\left[k\right]\left[l\right]$
$p\left[i\right]\left[j\right]=p\left[\frac i2\right]\left[j\right]+\sum_{l=1}^{j-1}dp\left[\frac i2\right]\left[j-l\right]p\left[\frac i2\right]\left[l\right]$
也就是说p可以由上一层的p加上一层的dp与p的卷积得到,而dp可以由上一层的dp自乘得到
那么自然可以用倍增p的第一层参数的方法,用FFT优化一下,一直做到n
时间效率为$O\left(mlogmlogn\right)$
注意:将n转化为二进制,那么为一的那些位,要在倍增完以后再推一层
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
struct complex{
double x,y;
complex(double xx=0,double yy=0){x=xx;y=yy;}
complex operator +(const complex &b){return complex(x+b.x,y+b.y);}
complex operator -(const complex &b){return complex(x-b.x,y-b.y);}
complex operator *(const complex &b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
}A[100010],B[100010];
const double pi=acos(-1.0);
int n,m,limit=1,cnt=0,r[100010];
int MOD;
void fft(complex *a,double type){
int i,j,k,mid;complex x,y,wn,w;
for(i=0;i<limit;i++) if(i<r[i]) swap(a[i],a[r[i]]);
for(mid=1;mid<limit;mid<<=1ll){
wn=complex(cos(pi/mid),type*sin(pi/mid));
for(j=0;j<limit;j+=(mid<<1ll)){
w=complex(1,0);
for(k=0;k<mid;k++,w=w*wn){
x=a[j+k];y=a[j+k+mid]*w;
a[j+k]=x+y;a[j+k+mid]=x-y;
}
}
}
}
int now=1,w=0,g[100010]={0},p[100010]={0},f[100010]={0};
int a1,a2,a3;
void solve1(){
int i;
for(i=0;i<=limit;i++) A[i]=B[i]=complex(0,0);
for(i=0;i<=limit;i++) A[i].x=p[i],B[i].x=g[i];
fft(A,1);fft(B,1);
for(i=0;i<=limit;i++) A[i]=A[i]*B[i];
fft(A,-1);
for(i=1;i<=m;i++) p[i]=(p[i]+(int)(A[i].x/limit+0.5)%MOD)%MOD;
for(i=0;i<=limit;i++) A[i]=complex(0,0);
for(i=0;i<=limit;i++) A[i].x=g[i];
fft(A,1);
for(i=0;i<=limit;i++) A[i]=A[i]*A[i];
fft(A,-1);
for(i=1;i<=m;i++) g[i]=(int)(A[i].x/limit+0.5)%MOD;
}
void solve2(){
int i;
for(i=0;i<=limit;i++) A[i]=B[i]=complex(0,0);
for(i=1;i<=m;i++) A[i].x=f[i],B[i].x=g[i];
fft(A,1);fft(B,1);
for(i=0;i<=limit;i++) A[i]=A[i]*B[i];
fft(A,-1);
for(i=1;i<=m;i++) g[i]=(int)(A[i].x/limit+0.5)%MOD,p[i]=(p[i]+g[i])%MOD;
}
int main(){
m=read();MOD=read();n=read();a1=read();a2=read();a3=read();
int i;
a1%=MOD;a2%=MOD;a3%=MOD;
for(i=1;i<=m;i++) g[i]=p[i]=f[i]=((((((a1*i)%MOD)*i)%MOD)+a2*i%MOD)+a3)%MOD;
while(limit<=(m<<1ll)) limit<<=1ll,cnt++;
for(i=0;i<limit;i++) r[i]=((r[i>>1ll]>>1ll)|((i&1ll)<<(cnt-1ll)));
while((now<<1ll)<=n) now<<=1ll,w++;
while(w){
w--;
solve1();//倍增
if(n&(1<<w)) solve2();//这一位应该是个奇数的,再推一层
}
printf("%lld\n",p[m]%MOD);
}
[JSOI2012][bzoj4332] 分零食 [FFT]的更多相关文章
- FFT 【JSOI2012】bzoj4332 分零食 (未解决)
很不错的一道倍增优化dp?? 第一次做这类题挺难想的 题目大意: 有n个小朋友,m块糖. 给小朋友分糖,如果一个小朋友分不到糖,那他后面的小朋友也分不到糖. 每个小朋友有一个喜悦值,有三个参数,O,S ...
- 【bzoj4332】【JSOI2012】 分零食 生成函数 FFT
我们构造$f(x)$的生成函数$G(x)$,那么显然$[x^k]G(x)=Ok^2+Sk+U$ 那么显然,答案即为$\sum_{i=1}^{n} [x^m]G^i(x)$ 我们构造答案的生成函数$F( ...
- BZOJ 4332: JSOI2012 分零食 FFT+分治
好题好题~ #include <bits/stdc++.h> #define N 50020 #define ll long long #define setIO(s) freopen(s ...
- LGP5075【JSOI2012】分零食
. 题解: 令$F$为欢乐度$f(x) = Ox^2 + Sx + U$的生成函数,常数项为$0$: 令$G(x) = \sum_{i=0}^{A} F^i (x) $ $ans = [x^M]G;$ ...
- 【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)
4332: JSOI2012 分零食 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 119 Solved: 66 Description 这里是欢乐 ...
- [BZOJ 4332] [JSOI2012]分零食(DP+FFT)
[BZOJ 4332] [JSOI2012]分零食(DP+FFT) 题面 同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U.如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是\ ...
- bzoj千题计划309:bzoj4332: JSOI2012 分零食(分治+FFT)
https://www.lydsy.com/JudgeOnline/problem.php?id=4332 因为如果一位小朋友得不到糖果,那么在她身后的小朋友们也都得不到糖果. 所以设g[i][j] ...
- bzoj4332;vijos1955:JSOI2012 分零食
描述 这里是欢乐的进香河,这里是欢乐的幼儿园. 今天是2月14日,星期二.在这个特殊的日子里,老师带着同学们欢乐地跳着,笑着.校长从幼儿园旁边的小吃店买了大量的零食决定分给同学们.听到这个消息,所有同 ...
- BZOJ4332 JSOI2012 分零食 【倍增 + NTT】
题目链接 权限题BZOJ4332 题解 容易想到\(dp\) 设\(g[i][j]\)表示前\(i\)人分到\(j\)颗糖的所有方案的乘积之和 设\(f(x) = Ox^2 + Sx + U\) \[ ...
随机推荐
- 响应式网站布局要适应的当下主流手机屏幕的各个版本的分辨率有哪些(media query)
CSS宽有14种: 320.360.375.384.400.414.533.600.768.800.853.1024.1280.1366 CSS高有16种: 360.480.533.568.569.6 ...
- Oracle表连接学习笔记
目录 一.表连接类型 1.1 内连接 1.2 外连接 二.表连接方法 2.1 表连接方法分类 2.2 表连接方法特性区别 @ 一.表连接类型 表连接类型可以分为:内连接.外连接,在看<收获,不止 ...
- Jquery中的CheckBox、RadioButton、DropDownList的取值赋值实现代码
随着Jquery的作用越来越大,使用的朋友也越来越多.在Web中,由于CheckBox. Radiobutton . DropDownList等控件使用的频率比较高,就关系到这些控件在Jquery中的 ...
- Bootstrap HTML编码规范
语法 1.用两个空格来代替制表符(Tab)--这是唯一能保证在所有的环境下获得一致展现的方法. 2.嵌套元素应当缩进一次(即两个空格). 3.对于属性的定义,属性值确保全部都用双引(避免使用单引号). ...
- Bzoj 1081 [Ahoi2009] chess 中国象棋
bzoj 1081 [Ahoi2009] chess 中国象棋 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1801 状态比较难设,的确 ...
- 九、Linux 磁盘管理
Linux 磁盘管理 Linux磁盘管理好坏直接关系到整个系统的性能问题. Linux磁盘管理常用三个命令为df.du和fdisk. df:列出文件系统的整体磁盘使用量 du:检查磁盘空间使用量 fd ...
- inotifywait实时监控文件目录
一.inotify简介 inotify 是一种强大的.细粒度的.异步文件系统监控机制,它满足各种各样的文件监控需要,可以监控文件系统的访问属性.读写属性.权限属性.创建删除.移动等操作,也可以监控文件 ...
- JZOJ 5185. 【NOIP2017提高组模拟6.30】tty's sequence
5185. [NOIP2017提高组模拟6.30]tty's sequence (Standard IO) Time Limits: 1000 ms Memory Limits: 262144 KB ...
- python语言介绍
Python诞生于1989年,作者是吉多.范罗苏姆,人称龟叔,由C语言实现的. 1999年,基于python的web框架Zope 1诞生,标志着python向web领域迈出了第一步,现在这个框架好像不 ...
- 饭卡 HDU - 2546(dp)
电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够).所以大家 ...