bzoj 4555 [Tjoi2016&Heoi2016]求和 NTT 第二类斯特林数 等比数列求和优化
[Tjoi2016&Heoi2016]求和
Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 679 Solved: 534
[Submit][Status][Discuss]
Description
在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心。
现在他想计算这样一个函数的值:
S(i, j)表示第二类斯特林数,递推公式为:
S(i, j) = j ∗ S(i − 1, j) + S(i − 1, j − 1), 1 <= j <= i − 1。
边界条件为:S(i, i) = 1(0 <= i), S(i, 0) = 0(1 <= i)
你能帮帮他吗?
Input
输入只有一个正整数
Output
输出f(n)。由于结果会很大,输出f(n)对998244353(7 × 17 × 223 + 1)取模的结果即可。1 ≤ n ≤ 100000
Sample Input
3
Sample Output
87
HINT
Source
多谢大佬的blog,我自己写比较慢,所以直接贴了。
这题本来是来练多项式求逆的,但是好像其它方法也可以做。
然后就通过这样的方法解出了,我们都知道等比数列求和的第一项需要特殊考虑,所以g[1]=n
然后就是卷积的形式了,从n^2 log n-----------> n log n
1 #include<cstring> 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<algorithm> 6 7 #define ll long long 8 #define mod 998244353 9 #define G 3 10 #define N 100007 11 using namespace std; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 16 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 17 return x*f; 18 } 19 20 int n,num,L,inv; 21 int jc[N],ny[N],jcn[N]; 22 ll a[N<<2],b[N<<2],rev[N<<2]; 23 24 int fast_pow(int a,int b) 25 { 26 int ans=1; 27 while(b) 28 { 29 if (b&1) ans=(ll)ans*a%mod; 30 a=(ll)a*a%mod; 31 b>>=1; 32 } 33 return ans; 34 } 35 void NTT(ll *a,ll f) 36 { 37 for (ll i=0;i<num;i++) 38 if (i<rev[i]) swap(a[i],a[rev[i]]); 39 for (ll i=1;i<num;i<<=1) 40 { 41 ll wn=fast_pow(G,(mod-1)/(i<<1)); 42 for (ll j=0;j<num;j+=(i<<1)) 43 { 44 ll w=1; 45 for (ll k=0;k<i;w=(ll)w*wn%mod,k++) 46 { 47 ll x=a[j+k],y=(ll)w*a[j+k+i]%mod; 48 a[j+k]=(x+y>=mod)?x+y-mod:x+y,a[j+k+i]=(x-y<0)?x-y+mod:x-y; 49 } 50 } 51 } 52 if (f==-1) 53 { 54 for (ll i=1;i<num/2;i++) swap(a[i],a[num-i]); 55 for (ll i=0;i<num;i++) a[i]=(ll)a[i]*inv%mod; 56 } 57 } 58 int main() 59 { 60 n=read(); 61 jc[0]=1,ny[0]=1,jcn[0]=1; 62 for (int i=1;i<=n;i++) 63 jc[i]=(ll)jc[i-1]*i%mod,ny[i]=fast_pow(i,mod-2),jcn[i]=(ll)jcn[i-1]*ny[i]%mod; 64 for (int i=0;i<=n;i++) 65 a[i]=(ll)((i&1)?-1:1)*jcn[i]; 66 for (int i=2;i<=n;i++) 67 b[i]=(ll)(fast_pow(i,n+1)-i)*jcn[i]%mod*ny[i-1]%mod;b[1]=n; 68 for (num=1;num<=2*n;num<<=1,L++);if (L) L--;inv=fast_pow(num,mod-2); 69 for (int i=0;i<=num;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<L); 70 NTT(a,1),NTT(b,1); 71 for (int i=0;i<num;i++) 72 a[i]=(ll)a[i]*b[i]%mod; 73 NTT(a,-1); 74 int ans=1;//第一项的等比数列的影响 75 for (int i=1;i<=n;i++) 76 (ans+=(ll)fast_pow(2,i)*jc[i]%mod*a[i]%mod)%=mod; 77 ans=(ans+mod)%mod; 78 printf("%d\n",ans); 79 }