写的时候要些变换主要就是抓住1.明白自变量的范围。2.卷积里两个自变量的和是一个常数。3.长度时大于等于实际的二倍的。
还有这题网上大多数的题目推导都是有问题的(导致常数过大,推导是正确的),或者有些小哥的姿势不对,也导致常数过大然后就卡了。。。。尼玛,卡常啊这题。。。。。。分析看下面:
对于任意模数,如果我们要求ans%p,p是任意模数,但是我们只能求mod费马素数的ntt,解决办法就是先算出真正值即还木有模p之前的值,然后再模p这样的话就好了。
先选三个费马素数 m1,m2,m3然后求出ans(modm1*m2*m3)由于ans的最大值都是小于m1*m2*m3的,所以ans%(m1*m2*m3)=ans然后求出来后再ans%p就好了,阔能要高精度
然后就搞吧。
这题的特点就是当你求出了此题的式子以后你会发现变量中的下标是和位置有关的,这时你需要做的就是做变量代换将下标换到和式中
比如此题就是
A[i] = revJ[i]; B[n - i] = ((J[i-1] * pow2[n - i]) % mod)*a[i]; 你会发现如果我们让i+k=t 然后 和式就是 A[i]*B[n-t]的形式 i是0-n-k变化的 而且 i+t=n-k是固定的所以现在就变好了注意t当然是大于等于1的,把我下面推导的公式换下就好了,这样写好理解一点
#include<iostream>
#include<cstdio>
#include<functional>
#include<algorithm>
using namespace std;
typedef long long ll;
const long long mod = 998244353;//
const long long g = 3;
long long n;
long long last = 0, llast = 1;
long long pow2[120000], revJ[120000], J[120000], wn[100];
long long A[400500], B[400500], a[400500], f[400500];
void exgcd(long long a, long long b, long long &x, long long &y)
{
if (b == 0)
{
x = 1, y = 0; return;
}
else
{
exgcd(b, a%b, y, x);
long long kk1 = (a / b) % mod; long long kk2 = x%mod;
y -= kk1*kk2;//这不是y-=a/b;
y = (y%mod + mod) % mod;
}
}
long long pow(long long value, long long times)
{
long long ans = 1; long long temp = value;
for (; times; times = times / 2)
{
if (times & 1)ans = (ans*temp) % mod;
temp = (temp*temp) % mod;
}
return ans;
}
void rander(long long *a, long long len)
{
for (long long i = 1, j = len / 2; i < len - 1; i++)
{
if (i < j)
{
swap(a[i], a[j]);
}
long long N = len / 2;
while (N <= j)
{
j -= N;
N /= 2;
}
j += N;
}
}
void init(int len)
{
if (last < len)
last = len;
else
return;
long long rr, ss;
for (int i = llast; i <= last; i++)
{
exgcd(i, mod, rr, ss);
revJ[i] = (revJ[i - 1] * rr) % mod;
pow2[i] = (pow2[i - 1] * 2) % mod;
J[i] = (J[i - 1] * i) % mod;
}
}
void ntt(long long *a, long long len, int kind)
{
rander(a, len); long long change1, change2;
for (int s = 1; (1 << s) <= len; s++)
{
long long m = (1 << s);
for (int k = 0; k < len; k += m)
{
long long w = 1;
for (int j = k; j < k + m / 2; j++)
{
long long left = a[j];
long long right = (w*a[j + m / 2]) % mod;
a[j] = (left + right) % mod; a[j + m / 2] = ((left - right) % mod + mod) % mod;
w = (w*wn[s]) % mod;
}
}
}
if (kind == -1)
{
for (int i = 1; i < len / 2; i++)swap(a[i], a[len - i]);
long long tempp; long long t = 1;
exgcd(len, mod, t, tempp);
for (int i = 0; i < len; i++)
a[i] = (t*(a[i] % mod)) % mod;
}
}
int main()
{
for (int i = 0; i<21; i++)
{
int t = 1 << i;
wn[i] = pow(g, (mod - 1) / t);
}
int t;
scanf("%d", &t);
revJ[0] = 1; J[0] = 1; pow2[0] = 1;
while (t--)
{
scanf("%d", &n);
//n = 20;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);//a[i] = 1000000000;
sort(a + 1, a + n + 1, greater<ll>());
init(n);
for (int i = 0; i < n; i++)
{
A[i] = revJ[i];
//B[n - 1 - i] = (((J[i] * pow2[n - 1 - i]) % mod) * a[i]) % mod;
}
for (int i = 1; i <= n; i++)
B[n - i] = ((J[i-1] * pow2[n - i]) % mod)*a[i];
long long len = 1;
while (len / 2 < (n))len *= 2;
for (int i = n; i < len; i++)A[i] = 0, B[i] = 0;//为什么要这一步?因为在推导fft的时候你会发现我们用的是矩阵来运算的所以不能只考虑w1 w2 ..wn-1而忽略了wn..wlen。
ntt(A, len, 1);
ntt(B, len, 1);
for (int i = 0; i <len; i++)
A[i] = (A[i] * B[i]) % mod;
ntt(A, len, -1);
f[0] = 0;
for (int i = 1; i <= n; i++)
{
f[i] = A[n - i] * revJ[i - 1] % mod;
f[i] = (f[i] + f[i - 1]) % mod;
printf("%lld ", f[i]);
}
printf("\n");
}
}
注意B[n-1-i]=...中的A[i]与上面的A[i]不是同一个。。。。为什么这样写网上有很多题解,就是公式推导后常数有点大,改成我这样就好 了!!!!!!
这里推荐一个小哥的,只是他的代码过不了看分析就好http://blog.csdn.net/cqu_hyx/article/details/52194696
/*是这样的,这几天在写 FFT,由于是在模意义下的,需要各种素数……
素数 rr kk gg
3 1 1 2
5 1 2 2
17 1 4 3
97 3 5 5
193 3 6 5
257 1 8 3
7681 15 9 17
12289 3 12 11
40961 5 13 3
65537 1 16 3
786433 3 18 10
5767169 11 19 3
7340033 7 20 3
23068673 11 21 3
104857601 25 22 3
167772161 5 25 3
469762049 7 26 3
998244353 119 23 3
1004535809 479 21 3
2013265921 15 27 31
2281701377 17 27 3 //以上素数都是常用的下面的话需要加高精度
3221225473 3 30 5
75161927681 35 31 3
77309411329 9 33 7
206158430209 3 36 22
2061584302081 15 37 7
2748779069441 5 39 3
6597069766657 3 41 5
39582418599937 9 42 5
79164837199873 9 43 5
263882790666241 15 44 7
1231453023109121 35 45 3
1337006139375617 19 46 3
3799912185593857 27 47 5
4222124650659841 15 48 19
7881299347898369 7 50 6
31525197391593473 7 52 3
180143985094819841 5 55 6
1945555039024054273 27 56 5
4179340454199820289 29 57 3