bzoj 4555 [Tjoi2016&Heoi2016]求和 NTT 第二类斯特林数 等比数列求和优化

[Tjoi2016&Heoi2016]求和

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 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 }

 

posted @ 2018-03-27 18:02  Kaiser-  阅读(239)  评论(0编辑  收藏  举报