bzoj 4332: JSOI2012 分零食 快速傅立叶变换
题目:
Description
同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U。如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是\(f(x)=O*x^2+S*x+U\)
现在校长开始分糖果了,一共有M个糖果。有些小朋友可能得不到糖果,对于那些得不到糖果的小朋友来说,欢乐程度就是1。如果一位小朋友得不到糖果,那么在她身后的小朋友们也都得不到糖果。(即这一列得不到糖果的小朋友一定是最后的连续若干位)
所有分糖果的方案都是等概率的。现在问题是:期望情况下,所有小朋友的欢乐程度的乘积是多少?呆呆同学很快就有了一个思路,只要知道总的方案个数T和所有方案下欢乐程度乘积的总和S,就可以得到答案Ans=S/T。现在他已经求出来了T的答案,但是S怎么求呢?他就不知道了。你能告诉他么?
因为答案很大,你只需要告诉他S对P取模后的结果。
题解:
首先这道题我们可以考虑枚举一下有多少人得到了零食
设\(g[i][j]\)表示\(i\)个人里分下去了\(j\)个零食得到的值,n为人数,m为零食数
这样我们有\(ans = \sum_{i=1}^ng[i][m]\)
\(g[i][j]\)的递推我们有
\]
其中\(F(k)\)表示将\(k\)个零食分给一个人得到的权
然后我们惊奇地发现后面的式子是一个卷积的形式
所以我们可以得到\(g_i = g_{i-1}*F\)
由于卷积满足结合律,所以我们有\(g_i = g_0*F^i\)
这样的话我们能够完成\(nlogn\)的单点求值,但是我们要求的是\(g_i\)的一个和
我们把答案\(ans\)拓展为一个多项式\(f(x)\),答案储存在第f(n)的第\(m\)位
则有\(f_n = \sum_{i=1}^{n}g_i\)
然后我们发现:
\]
\]
在继续推导之前首先我们需要证明: \(g_{i+j} = g_i*g_j\)
由\(g_i = g_0*F^i\)可得:\(g_i*g_j = g_0*g_0*F^i*F^j\)
因为:\(g_0*g_0 = g_0\)所以有\(g_0*g_0*F^i*F^j = g_0*F^i*F^j = g_{i+j}\)得证
所以继续上式的推导我们有
\]
我们将卷积的形式再拆解开来:
\]
\]
\]
\]
我们又知道:
\]
所以迭代倍增即可求解
复杂度\(O(nlog^2n)\)
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 41000;
const double pi = acos(-1);
int mod;
struct complex{
long double x,y;
complex(){x=y=0;}
complex(long double a,long double b){x=a;y=b;}
complex operator + (const complex &r){return complex(x+r.x,y+r.y);}
complex operator - (const complex &r){return complex(x-r.x,y-r.y);}
complex operator * (const complex &r){return complex(x*r.x-y*r.y,x*r.y+y*r.x);}
complex operator / (const long double &r){return complex(x/r,y/r);}
};
inline void FFT(complex *x,int n,int p){
for(int i=0,t=0;i<n;++i){
if(i > t) swap(x[i],x[t]);
for(int j=n>>1;(t^=j) < j;j>>=1);
}
for(int m=2;m<=n;m<<=1){
int k = m>>1;
complex wn(cos(p*2*pi/m),sin(p*2*pi/m));
for(int i=0;i<n;i+=m){
complex w(1,0),u;
for(int j=0;j<k;++j,w=w*wn){
u = x[i+j+k]*w;
x[i+j+k] = x[i+j] - u;
x[i+j] = x[i+j] + u;
}
}
}
if(p == -1 ) for(int i=0;i<n;++i) x[i] = x[i]/n;
}
complex ca[maxn],cb[maxn],cc[maxn];int len,m;
inline int mul(int *a,int *b,int *c){
for(int i=0;i<len;++i){
ca[i] = complex((long double)a[i],0);
cb[i] = complex((long double)b[i],0);
}
FFT(ca,len,1);FFT(cb,len,1);
for(int i=0;i<len;++i) cc[i] = ca[i]*cb[i];
FFT(cc,len,-1);
for(int i=0;i<=m;++i){
c[i] = ((int)floor(cc[i].x + 0.5)) % mod;
}
}
int f[maxn],g[maxn],arr[maxn],tmp[maxn];
inline void qpow(int k){
if(k == 1){
for(int i=0;i<=m;++i) f[i] = g[i] = arr[i];
return ;
}qpow(k>>1);
mul(f,g,tmp);mul(g,g,g);
for(int i=0;i<=m;++i){
f[i] += tmp[i];
if(f[i] >= mod) f[i] -= mod;
}
if(k&1){
mul(g,arr,g);
for(int i=0;i<=m;++i){
f[i] += g[i];
if(f[i] >= mod) f[i] -= mod;
}
}
}
int main(){
read(m);read(mod);
for(len = 1;(len) <= (m<<1);len<<=1);
int n,a,b,c;read(n);read(a);read(b);read(c);
a %= mod;b %= mod;c %= mod;
for(int i=1;i<=m;++i) arr[i] = ((a*i*i % mod) + (b*i % mod) + c) % mod;
qpow(n);printf("%d\n",f[m]);
getchar();getchar();
return 0;
}
bzoj 4332: JSOI2012 分零食 快速傅立叶变换的更多相关文章
- [BZOJ 4332] [JSOI2012]分零食(DP+FFT)
[BZOJ 4332] [JSOI2012]分零食(DP+FFT) 题面 同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U.如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是\ ...
- BZOJ 4332: JSOI2012 分零食 FFT+分治
好题好题~ #include <bits/stdc++.h> #define N 50020 #define ll long long #define setIO(s) freopen(s ...
- 【BZOJ 4332】 4332: JSOI2012 分零食 (FFT+快速幂)
4332: JSOI2012 分零食 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 119 Solved: 66 Description 这里是欢乐 ...
- BZOJ 2194 快速傅立叶变换之二 | FFT
BZOJ 2194 快速傅立叶变换之二 题意 给出两个长为\(n\)的数组\(a\)和\(b\),\(c_k = \sum_{i = k}^{n - 1} a[i] * b[i - k]\). 题解 ...
- 为什么要进行傅立叶变换?傅立叶变换究竟有何意义?如何用Matlab实现快速傅立叶变换
写在最前面:本文是我阅读了多篇相关文章后对它们进行分析重组整合而得,绝大部分内容非我所原创.在此向多位原创作者致敬!!!一.傅立叶变换的由来关于傅立叶变换,无论是书本还是在网上可以很容易找到关于傅立叶 ...
- 离散傅立叶变换与快速傅立叶变换(DFT与FFT)
自从去年下半年接触三维重构以来,听得最多的词就是傅立叶变换,后来了解到这个变换在图像处理里面也是重点中的重点. 本身自己基于高数知识的理解是傅立叶变换是将一个函数变为一堆正余弦函数的和的变换.而图像处 ...
- 快速傅立叶变换(FFT)算法
已知多项式f(x)=a0+a1x+a2x2+...+am-1xm-1, g(x)=b0+b1x+b2x2+...+bn-1xn-1.利用卷积的蛮力算法,得到h(x)=f(x)g(x),这一过程的时间复 ...
- $\mathcal{FFT}$·$\mathcal{Fast \ \ Fourier \ \ Transformation}$快速傅立叶变换
\(2019.2.18upd:\) \(LINK\) 之前写的比较适合未接触FFT的人阅读--但是有几个地方出了错,大家可以找一下233 啊-本来觉得这是个比较良心的算法没想到这么抽搐这个算法真是将一 ...
- 快速傅立叶变换(FFT)
多项式 系数表示法 设\(f(x)\)为一个\(n-1\)次多项式,则 \(f(x)=\sum\limits_{i=0}^{n-1}a_i*x_i\) 其中\(a_i\)为\(f(x)\)的系数,用这 ...
随机推荐
- js页面跳转,url带url参数解决方案
今天,在做一个项目的时候,向后端发送了一个Ajax请求,后端返回了一个字符串,告诉我未登录.那么我需要跳转到登录页面,同时告诉登录页面,登录成功后,需要跳回的url.也就是标题所说,url中的一个参数 ...
- VisualSVN Server的迁移
VisualSVN Server迁移涉及到两种情况: 第一种情况:VisualSVN Server没有更换电脑或者服务器,只是修改Server name. 第二种情况:当VisualSVN Serve ...
- 亚马逊:PS4和Xbox One实在太火
圣诞节刚刚结束,当实体零售商在抱怨坑爹的天气让自己节日生意变得冷清的同时,在线零售商们却依旧赚的盆满钵满. 亚马逊近日表示,今年节日期间的零售工作非常不错,新一代游戏机更是最大的亮点.据销售统计,在圣 ...
- Scrum立会报告+燃尽图(十月二十三日总第十四次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2246 项目地址:https://git.coding.net/zhang ...
- week1:个人博客作业
1.软件工程课程的希望和目标 老师步置的任务完整的做完,每一步都是自己做的,明白自己做的每一步,和为什么这样做. 期末考试最后为95分以上,最好是100. 每周学习这门课时间 每周2节课(90分钟)+ ...
- C++ Primer Plus学习:第五章
C++入门第五章:循环和关系表达式 for循环 for循环的组成部分 设置初始值. 执行测试,看循环是否应该继续执行. 执行循环操作. 更新用于测试的值. 以上操作由括号括起,每个部分均是一个表达式, ...
- texbbox,combobox设置属性
--输入框 $("#xx").textbox('setValue','value'); //设置输入框的值 $('#xx').textbox('textbox').attr('r ...
- vsftpd:非常安全的ftp服务端程序
主程序:/usr/sbin/vsftpd 主配置文件:/etc/vsftpd/vsftpd.conf CentOS 6 /etc/rc.d/init.d/vsftpd chkconfig vsftp ...
- Java多线程 -join用法
阿里面试官问我这个问题,我仔细总结了一下: 参考:sleep.yield.wait.join的区别(阿里面试) 1. join()介绍 join() 定义在Thread.java中.join() 的作 ...
- 怎么用JavaScript实现tab切换
先看一下代码实现后的最终效果: 用JavaScript实现思路很简单,就是先把所有的内容隐藏,点击标题对应的内容显示, css代码如下: <style type="text/css&q ...