Partial Sums V2
题目连接:
Description
给出一个数组A,经过一次处理,生成一个 数组S,数组S中的每个值相当于数组A的累加,比如:A = {1 3 5 6} => S = {1 4 9 15}。如果对生成的数组S再进行一次累加操作,{1 4 9 15} => {1 5 14 29},现在给出数组A,问进行K次操作后的结果。(输出结果 Mod 10^9 + 7)
Input 第1行,2个数N和K,中间用空格分隔,N表示数组的长度,K表示处理的次数(2 <= n <= 50000, 0 <= k <= 10^9, 0 <= a[i] <= 10^9)
Output 共N行,每行一个数,对应经过K次处理后的结果。输出结果 Mod 10^9 + 7。
Sample Input 4 2
1
3
5
6
Sample Output 1
5
14
29
题意: 题解: 考虑每个位置的贡献,所求即$ans[n]=\sum_{i+j=n}^{}C(k-1+i,i)\cdot a[j]$ ,其中 $C(n,i) $表示从 n 个物品里选出 i 个物品的方案数。
上述卷积形式可以利用FFT或NTT加速运算,难点在于答案模 109+7,设其为 P ,这意味这参与卷积的每个元素值为不大于 (P−1) 的非负整数,卷积后的值为不大于 (n+1)⋅(P−1)2=O(nP2) 的值,这个上界可以达到 5⋅1022 。
一种想法是利用3种模意义下的NTT结果进行合并,得到这个可能达到 5⋅1022 的数,再取模,一共需要9次NTT,涉及高精度。
还有一种想法就是降低卷积前的元素值上界,令 M 为满足 P≤M2 的最小正整数,将多项式 f 拆成 f1+f2⋅M 的形式,那么每个元素的值上界是 O(M)=O($\sqrt{p}$) 的,卷积后的值上界是 O(nP) 的,用long double来做FFT差不多可以接受,而卷积可以写为 f∗g=(f1+f2⋅M)∗(g1+g2⋅M)=(f1∗f2)+(f1∗g2+f2∗g1)⋅M+(f2∗g2)⋅M2 ,一共需要7次FFT,不涉及高精度。
很邪,51nod上c++会wa,c++11会过..
以前只在大牛的博客上看到过第一种做法,但没有实用性,第二种方法很强。
昨天刚好看到,拉出来封个版
----------
2016-8-18 更新
看到另一种黑科技优化,大概是fft中用了相位的部分,只用4次fft,膜
代码
1 //#include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include
::iterator iter;133 //for(int x=1;x<=n;x++)134 //for(int y=1;y<=n;y++)135 //scanf("%d",&a);136 //printf("%d\n",ans);137 int n;138 LL k;139 scanf("%d%lld",&n,&k);140 inv[1]=1;141 for(int x=2;x