【JSOI2012】 分零食 生成函数 FFT

我们构造$f(x)$的生成函数$G(x)$,那么显然$[x^k]G(x)=Ok^2+Sk+U$

那么显然,答案即为$\sum_{i=1}^{n} [x^m]G^i(x)$

我们构造答案的生成函数$F(x)=\sum_{i=1}^{n} G^i(x)$

根据等比数列求和公式,$F(x)=\dfrac{1-G(x)}{1-G^{A+1}(x)}$

如果去等比数列求和的话,你需要多项式快速幂+多项式求逆,时间复杂度显然是$O(m\ log\ m)$的。

然而这个模数并不是质数,所以这么搞不是很好搞。

我们可以用一个类似快速幂的方式,去算出$\sum_{i-1}^{2^k-1}G^i(x)$的值。

这么搞的时间复杂度显然是$O(m\ log\ m\ log\ A)$。

然后就没了

第一次自己推出生成函数的题美滋滋

 1 #include<bits/stdc++.h>
 2 #define MOD 998244353
 3 #define L long long
 4 #define M 1<<15
 5 #define G 3
 6 using namespace std;
 7
 8 L pow_mod(L x,L k){
 9     L ans=1;
10     while(k){
11         if(k&1) ans=ans*x%MOD;
12         x=x*x%MOD; k>>=1;
13     }
14     return ans;
15 }
16 void change(L a[],int n){
17     for(int i=0,j=0;i<n-1;i++){
18         if(i<j) swap(a[i],a[j]);
19         int k=n>>1;
20         while(j>=k) j-=k,k>>=1;
21         j+=k;
22     }
23 }
24 void NTT(L a[],int n,int on){
25     change(a,n);
26     for(int h=2;h<=n;h<<=1){
27         L wn=pow_mod(G,(MOD-1)/h);
28         for(int j=0;j<n;j+=h){
29             L w=1;
30             for(int k=j;k<j+(h>>1);k++){
31                 L u=a[k],t=w*a[k+(h>>1)]%MOD;
32                 a[k]=(u+t)%MOD;
33                 a[k+(h>>1)]=(u-t+MOD)%MOD;
34                 w=w*wn%MOD;
35             }
36         }
37     }
38     if(on==-1){
39         L inv=pow_mod(n,MOD-2);
40         for(int i=0;i<n;i++) a[i]=a[i]*inv%MOD;
41         reverse(a+1,a+n);
42     }
43 }
44 L m,P,A,O,S,U;
45 L g[M]={0},gsum[M]={0},ans[M]={0};
46
47 int main(){
48     cin>>m>>P>>A>>O>>S>>U;
49     for(L i=1;i<=m;i++) g[i]=(O*i*i+S*i+U)%P;
50     int len=1; while(len<=(m*2)) len<<=1;
51     gsum[0]=1;
52     A=min(A,m);
53     while(A){
54
55         if(A&1){
56             NTT(ans,len,1); NTT(g,len,1);
57             for(int i=0;i<len;i++) ans[i]=ans[i]*g[i]%MOD;
58             NTT(ans,len,-1); NTT(g,len,-1);
59             for(int i=1;i<=m;i++)
60             ans[i]=(ans[i]+g[i]+gsum[i])%P;
61             for(int i=m+1;i<len;i++) ans[i]=0;
62         }
63         A>>=1;
64
65         g[0]++;
66         NTT(g,len,1); NTT(gsum,len,1);
67         for(int i=0;i<len;i++) gsum[i]=gsum[i]*g[i]%MOD;
68         NTT(g,len,-1); NTT(gsum,len,-1);
69         g[0]--;
70         for(int i=0;i<len;i++) if(i>m) gsum[i]=0; else gsum[i]%=P;
71
72         NTT(g,len,1);
73         for(int i=0;i<len;i++) g[i]=g[i]*g[i]%MOD;
74         NTT(g,len,-1);
75         for(int i=0;i<len;i++) if(i>m) g[i]=0; else g[i]%=P;
76     }
77     cout<<ans[m]<<endl;
78 }

原文地址:https://www.cnblogs.com/xiefengze1/p/9371042.html

时间: 2024-10-10 10:15:45

【JSOI2012】 分零食 生成函数 FFT的相关文章

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

4332: JSOI2012 分零食 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 119  Solved: 66 Description 这里是欢乐的进香河,这里是欢乐的幼儿园. 今天是2月14日,星期二.在这个特殊的日子里,老师带着同学们欢乐地跳着,笑着.校长从幼儿园旁边的小吃店买了大量的零食决定分给同学们.听到这个消息,所有同学都安安静静地排好了队,大家都知道,校长不喜欢调皮的孩子. 同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐

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

https://www.lydsy.com/JudgeOnline/problem.php?id=4332 因为如果一位小朋友得不到糖果,那么在她身后的小朋友们也都得不到糖果. 所以设g[i][j] 表示前i位小朋友,分到j个糖果,且前i位小朋友都分到糖果的方案数 令F(x) 表示分到x个糖果的欢乐程度 ∴g[i][j] = ∑ g[i-1][j-k]*F(k) 记g[i]=g[i-1]*F,则 g[i]=F ^ i 但是要求的是 Σ g[i][m] 记f[n]=Σ g[i]  i∈[1,n]

vijos1955:JSOI2012 分零食

描述 这里是欢乐的进香河,这里是欢乐的幼儿园. 今天是2月14日,星期二.在这个特殊的日子里,老师带着同学们欢乐地跳着,笑着.校长从幼儿园旁边的小吃店买了大量的零食决定分给同学们.听到这个消息,所有同学都安安静静地排好了队,大家都知道,校长不喜欢调皮的孩子. 同学们依次排成了一列,其中有A位小朋友,有三个共同的欢乐系数O,S和U.如果有一位小朋友得到了x个糖果,那么她的欢乐程度就是f(x)=Ox^2+Sx+U. 现在校长开始分糖果了,一共有M个糖果.有些小朋友可能得不到糖果,对于那些得不到糖果的

bzoj4332[JSOI2012]分零食

一下午被这题的精度续掉了...首先可以找出一个多项式的等比数列的形式,然后类似poj的Matrix Series,不断倍增就可以了.用复数点值表示进行多次的多项式运算会刷刷地炸精度...应当用int存多项式,然后卷积的时候再dft成复数,卷积之后idft回实数.注意两个m次的多项式卷积之后会变成2m次的多项式,多项式的后一半需要清零. #include<cstdio> #include<cstring> #include<cmath> #include<algor

CF528D Fuzzy Search (生成函数+FFT)

题目传送门 题目大意:给你两个只包含A,G,C,T的字符串$S$,$T$,$S$长$T$短,按照如下图方式匹配 解释不明白直接上图 能容错的距离不超过$K$,求能$T$被匹配上的次数 $S$串同一个位置可以被$T$的不同位置匹配多次 对4种字符分别处理,假设我们现在只讨论字符A 对于字符串AGCAATTCAT,字符A的生成函数就是1001100010 题目要求距离不超过K就能匹配,把周围距离不超过$K$的位置都变成1,形成一个新串$S'$ $S$  1001100010 $S'$ 1111110

【BZOJ3771】Triple 生成函数+FFT

[BZOJ3771]Triple Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: “这把斧头,是不是你的?” 樵夫一看:“是啊是啊!” 水神把斧头扔在一边,又拿起一个东西问: “这把斧头,是不是你的?” 樵夫看不清楚,但又怕真的是自己的斧头,只好又答:“是啊是啊!” 水神又把手上的东西扔在一边,拿起第三个东西问: “这把斧头,是不是你的?” 樵夫还是看不清楚,但是他觉得再这样下去他就没法砍柴了. 于是他又一次答:“

HDU 5307 He is Flying (生成函数+FFT)

题目传送门 给你一个长度为$n$的自然数序列$a$,定义一段区间的权值为这一段区间里所有数的和,分别输出权值为$[0,\sum a_{i}]$的区间的长度之和 想到了生成函数的话,这道题并不难做.但很多细节真是不太好搞 我们首先预处理出前缀和s,那么一段区间$[l,r]$的权值就是$s_{r}-s_{l-1}$ 容易联想到卷积 第一个多项式是 区间右端点的前缀和 作为指数的生成函数,每一项的系数是 右端点的编号之和 第二个多项式是 区间左端点的前缀和 作为指数的生成函数,每一项的系数是 左端点的

UVA 12633 Super Rooks on Chessboard (生成函数+FFT)

题面传送门 题目大意:给你一张网格,上面有很多骑士,每个骑士能横着竖着斜着攻击一条直线上的格子,求没被攻击的格子的数量总和 好神奇的卷积 假设骑士不能斜着攻击 那么答案就是没被攻击的 行数*列数 接下来考虑斜着攻击对答案的贡献 以左下角为坐标原点建立坐标系,发现一条对角线的点的$(x+y)$坐标是相同的 考虑卷积,设计两个生成函数$a,b$ 如果第i行没骑士,则$a_{i}=1$,反之为$0$ 如果第i列没骑士,则$b_{i}=1$,反之为$0$ 我们对两个式子进行卷积,可以求出每一条对角线上还

【2017 4 12 总结】

今天做JSOI2012的题. 才120,其实是可以拿很多部分分什么的,但是都打错... (代码实现能力太差了. 1. 4330: JSOI2012 爱之项链 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 50  Solved: 24 Description 在进香河,流传着这样一段美丽的故事.zyg与kzn是两个生活在进香河的孩子,一天,他们两人闹矛盾了,于是zyg送给了kzn一条精美的爱之项链.从此他们幸福生活在一起. 这则故事的真实性到今天已