聯考20200723 T1 數
阿新 • • 發佈:2020-07-23
分析:
題解看不懂,同機房究極巨佬給了另一種做法
直接開始化式子:
\[Ans_m \]
\[=\sum_{i=0}^{n}a_i\sum_{j=0}^{n}(-1)^j\binom{m}{j}\binom{n-m}{i-j} \]
\[=\sum_{i=0}^{n}a_i[x^i]((1+x)^{n-m}(1-x)^m) \]
\[=\sum_{i=0}^{n}a_i[x^i]((1+x)^{n-m}(2-(1+x))^m) \]
\[=\sum_{i=0}^{n}a_i[x^i](\sum_{j=0}^{m}(-1)^{m-j}2^j\binom{m}{j}(1+x)^{n-j}) \]
\[=\sum_{j=0}^{m}(-1)^{m-j}2^j\binom{m}{j}\sum_{i=0}^{n}a_i[x^i](1+x)^{n-j} \]
\[=\sum_{j=0}^{m}(-1)^{m-j}2^j\binom{m}{j}\sum_{i=0}^{n-j}a_i[x^i](1+x)^{n-j} \]
\[=\sum_{j=0}^{m}(-1)^{m-j}2^j\binom{m}{j}\sum_{i=0}^{n-j}a_i\binom{n-j}{i} \]
全程只需使用二項式定理
撲通撲通跪下來
後面這個\(F_{n-j}=\sum_{i=0}^{n-j}a_i\binom{n-j}{i}\)是卷積的形式,用一次NTT快速求出所有\(F\)
變成:
\[Ans_m=\sum_{j=0}^{m}(-1)^{m-j}2^jF_{n-j} \]
又是一個卷積的形式,再次使用NTT快速求出所有\(Ans\)
(日常被開除人籍系列)
複雜度\(O(nlogn)\)
OJ很慢(自己人菜常數大),\(10^6\)卡不過去(悲)
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<set> #include<map> #include<vector> #include<string> #define maxn 2500005 #define INF 0x3f3f3f3f #define MOD 998244353 using namespace std; inline long long getint() { long long num=0,flag=1;char c; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1; while(c>='0'&&c<='9')num=num*10+c-48,c=getchar(); return num*flag; } int n; int A[maxn],B[maxn],F[maxn]; int rev[maxn]; int a[maxn],S,M,BB; int Wl,Wl2,w[maxn]; int fac[maxn],inv[maxn],pw2[maxn]; unsigned int Ans,pw[maxn]; inline int upd(int x){return x<MOD?x:x-MOD;} inline int ksm(int num,int k) { int ret=1; for(;k;k>>=1,num=1ll*num*num%MOD)if(k&1)ret=1ll*ret*num%MOD; return ret; } inline void init(int N) { Wl=w[0]=1; while((Wl<<1)<=N)Wl<<=1; w[1]=ksm(3,(MOD-1)/(Wl<<1)),Wl2=Wl<<1; for(int i=2;i<=Wl2;i++)w[i]=1ll*w[i-1]*w[1]%MOD; } inline void NTT(int *a,int N,int opt) { for(int i=0;i<N;i++)if(i<rev[i])swap(a[i],a[rev[i]]); for(int i=1,B=Wl;i<N;i<<=1,B>>=1) for(int j=0,t=i<<1;j<N;j+=t)for(int k=0,x=0;k<i;k++,x+=B) { int v=1ll*a[i+j+k]*w[opt==1?x:Wl2-x]%MOD; a[i+j+k]=upd(a[j+k]-v+MOD),a[j+k]=upd(a[j+k]+v); } if(!~opt)for(int i=0,Inv=ksm(N,MOD-2);i<N;i++)a[i]=1ll*a[i]*Inv%MOD; } inline int C(int p,int q) {return 1ll*fac[p]*inv[q]%MOD*inv[p-q]%MOD;} int main() { n=getint(),a[0]=getint(),S=getint(),M=getint(),BB=getint(); init(2*n);pw[0]=pw2[0]=1; for(int i=1;i<=n;i++)pw[i]=pw[i-1]*1000000007,pw2[i]=upd(pw2[i-1]+pw2[i-1]); for(int i=1;i<=n;i++)a[i]=(1ll*(a[i-1]^S)*M+BB)%MOD; fac[0]=fac[1]=inv[0]=inv[1]=1; for(int i=2;i<=n;i++)fac[i]=1ll*fac[i-1]*i%MOD; for(int i=2;i<=n;i++)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD; for(int i=2;i<=n;i++)inv[i]=1ll*inv[i]*inv[i-1]%MOD; int len=1; while(len<=2*n)len<<=1; for(int i=0;i<len;i++)rev[i]=(rev[i>>1]>>1)|(i&1?len>>1:0); for(int i=0;i<=n;i++)A[i]=1ll*a[i]*inv[i]%MOD,B[i]=inv[i]; NTT(A,len,1),NTT(B,len,1); for(int i=0;i<len;i++)A[i]=1ll*A[i]*B[i]%MOD; NTT(A,len,-1); for(int i=0;i<=n;i++)F[i]=1ll*A[i]*fac[i]%MOD; for(int i=0;i<len;i++)A[i]=B[i]=0; for(int i=0;i<=n;i++)A[i]=1ll*pw2[i]*inv[i]%MOD*F[n-i]%MOD,B[i]=i&1?MOD-inv[i]:inv[i]; NTT(A,len,1),NTT(B,len,1); for(int i=0;i<len;i++)A[i]=1ll*A[i]*B[i]%MOD; NTT(A,len,-1); for(int i=0;i<=n;i++)F[i]=1ll*A[i]*fac[i]%MOD; for(int i=0;i<=n;i++)Ans+=((unsigned int)F[i])*pw[i]; cout<<Ans<<endl; }