题面

传送门

思路

首先,这个数据如果没有这么大,我们还是可以做朋友的......

设$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]的更多相关文章

  1. FFT 【JSOI2012】bzoj4332 分零食 (未解决)

    很不错的一道倍增优化dp?? 第一次做这类题挺难想的 题目大意: 有n个小朋友,m块糖. 给小朋友分糖,如果一个小朋友分不到糖,那他后面的小朋友也分不到糖. 每个小朋友有一个喜悦值,有三个参数,O,S ...

  2. 【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( ...

  3. BZOJ 4332: JSOI2012 分零食 FFT+分治

    好题好题~ #include <bits/stdc++.h> #define N 50020 #define ll long long #define setIO(s) freopen(s ...

  4. LGP5075【JSOI2012】分零食

    . 题解: 令$F$为欢乐度$f(x) = Ox^2 + Sx + U$的生成函数,常数项为$0$: 令$G(x) = \sum_{i=0}^{A} F^i (x) $ $ans = [x^M]G;$ ...

  5. 【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)

    4332: JSOI2012 分零食 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 119  Solved: 66 Description 这里是欢乐 ...

  6. [BZOJ 4332] [JSOI2012]分零食(DP+FFT)

    [BZOJ 4332] [JSOI2012]分零食(DP+FFT) 题面 同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U.如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是\ ...

  7. bzoj千题计划309:bzoj4332: JSOI2012 分零食(分治+FFT)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4332 因为如果一位小朋友得不到糖果,那么在她身后的小朋友们也都得不到糖果. 所以设g[i][j] ...

  8. bzoj4332;vijos1955:JSOI2012 分零食

    描述 这里是欢乐的进香河,这里是欢乐的幼儿园. 今天是2月14日,星期二.在这个特殊的日子里,老师带着同学们欢乐地跳着,笑着.校长从幼儿园旁边的小吃店买了大量的零食决定分给同学们.听到这个消息,所有同 ...

  9. BZOJ4332 JSOI2012 分零食 【倍增 + NTT】

    题目链接 权限题BZOJ4332 题解 容易想到\(dp\) 设\(g[i][j]\)表示前\(i\)人分到\(j\)颗糖的所有方案的乘积之和 设\(f(x) = Ox^2 + Sx + U\) \[ ...

随机推荐

  1. RAC基本使用

    @interface ViewController () @property (weak, nonatomic) IBOutlet lwRedView *redView; @property (wea ...

  2. maven操作手册

    ===Maven的安装=== http://blog.csdn.net/yang5726685/article/details/56486479 ===Maven的jar包仓库地址配置=== http ...

  3. 回归树的原理及Python实现

    大名鼎鼎的 GBDT 算法就是用回归树组合而成的.本文就回归树的基本原理进行讲解,并手把手.肩并肩地带您实现这一算法. 1. 原理篇 1.1 最简单的模型 如果预测某个连续变量的大小,最简单的模型之一 ...

  4. matlplotlib 为折线图填充渐变颜色

    概要   本篇记录绘图时填充颜色时的一些常用设置,主要用到了 imshow,fill 函数.   填充图实例   填充的效果图如下: 图 1:渐变色效果图 可根据下方给出的代码进行自定义. #!/us ...

  5. bootstrap3 文档随看

    唉 昨天看的是2,早知道就只可以看3啦,虽然整体不变,但是小改小闹的还是很多啦.产品上线是需要升级的,但是像这么改会很烦哎,有些样式名字修改,用法修改,功能修改,那让用惯了2的人还得把之前记忆清除了然 ...

  6. Bootstrap历练实例:响应式导航

    <!DOCTYPE html><html lang="zh-cn"><head><meta http-equiv="Conten ...

  7. jQuery入门第一天-(一个菜鸟的不正经日常)

    jQuery的初步认识 菜鸟Q1:什么是jQuery? jQuery就是一个JavaScript函数库,没什么 特别的. 菜鸟Q2:jQuery能做什么?jQuery是做什么的? jQuery本身就是 ...

  8. restful api 规范

  9. Android系统编译环境及连接工具配置

    首先附上官网上关于环境搭建的地址:https://source.android.com/setup/build/initializing 官网目前建议的还是Ubuntu14.04,下面就是用的Ubun ...

  10. angularjs的使用技巧

    1. AngularJS的module函数有两种用法, a. 定义一个module, 需要传入2个参数,module('moduleName', []), 第一个参数是新的module名称,第二个参数 ...