Loj #6261. 一個人的高三樓
阿新 • • 發佈:2018-03-10
turn include obj fill -s loj ++ sin 大小 計算出 A 之後,直接一遍NTT 讓 a卷一下它,得到結果。
link : https://loj.ac/problem/6261
一看就是一個已經退役的大佬出的題。。。
我一開始還是too young了,忘了看時限,,以為NTT+多項式快速冪就能水過的。。。
於是就寫了個我代碼裏被我註釋掉的東西。。。。。
後來被卡了之後才想起來全是1的多項式的N次方的各個項的系數是可以直接用組合數算出來的。。。。
具體的說,設 A = {1,x,x^2,,,,,,,} ^ N 。
A中的 x^i 的系數就是 C(N+i-1,i) ,因為這就是可重組合的定義式吧23333。
而根據組合數的通項公式,我們可以很容易的從 x^i 的系數來遞推 x^(i+1) 的系數。
O(N)
寫的時候犯了很多SB錯誤,想想都想打自己23333.
1.一開始求補0之後序列長度的逆元求成補0之前的了,,,雖然這個樣例並不能看出來因為樣例 4=2^2 2333.
2. 數組大小一定要開到 > 卷積後最高次數 的2^k 。
3.K比較大,,,乘積的時候得先%ha之後再運算233
#include<bits/stdc++.h> #define ll long long #define maxn 400005 using namespace std; const int ha=998244353; const int root=3; const int inv=ha/3+1; ll k; int a[maxn],b[maxn],n,N; int INV,e[maxn],r[maxn],l; int object[2][maxn]; int ni[maxn]; inline int ksm(int x,int y){ int an=1; for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha; return an; } inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x; } inline void NTT(int *c,int f){ for(int i=0;i<N;i++) if(i<r[i]) swap(c[i],c[r[i]]); for(int i=1,o=1;i<N;i<<=1,o++){ int omega=object[f==-1][o]; for(int p=i<<1,j=0;j<N;j+=p){ int now=1; for(int u=0;u<i;u++,now=now*(ll)omega%ha){ int x=c[j+u],y=c[j+u+i]*(ll)now%ha; c[j+u]=add(x,y); c[j+u+i]=add(x,ha-y); } } } if(f==-1) for(int i=0;i<N;i++) c[i]=c[i]*(ll)INV%ha; } inline void calc(){ b[0]=1; for(int i=1;i<n;i++) b[i]=b[i-1]*((ll)(k+i-1)%ha)%ha*(ll)ni[i]%ha; } inline void solve(){ int len=(n-1)<<1; for(N=1,l=0;N<=len;N<<=1) l++; for(int i=0;i<N;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); for(int i=1;i<=l;i++){ object[0][i]=ksm(root,(ha-1)/(1<<i)); object[1][i]=ksm(inv,(ha-1)/(1<<i)); } INV=ksm(N,ha-2); ni[1]=1; for(int i=2;i<=n;i++) ni[i]=-ni[ha%i]*(ll)(ha/i)%ha+ha; calc(); /* while(k){ if(k&1){ NTT(a,1),NTT(b,1); for(int i=0;i<N;i++) a[i]=a[i]*(ll)b[i]%ha; NTT(a,-1),NTT(b,-1); fill(a+n,a+N,0); } NTT(b,1); for(int i=0;i<N;i++) b[i]=b[i]*(ll)b[i]%ha; NTT(b,-1); fill(b+n,b+N,0); k>>=1; } */ NTT(a,1),NTT(b,1); for(int i=0;i<N;i++) a[i]=a[i]*(ll)b[i]%ha; NTT(a,-1); } int main(){ scanf("%d%lld",&n,&k); for(int i=0;i<n;i++){ scanf("%d",a+i); } solve(); for(int i=0;i<n;i++) printf("%d\n",a[i]); return 0; }
Loj #6261. 一個人的高三樓