1. 程式人生 > >Loj #6261. 一個人的高三樓

Loj #6261. 一個人的高三樓

turn include obj fill -s loj ++ sin 大小

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)

計算出 A 之後,直接一遍NTT 讓 a卷一下它,得到結果。

寫的時候犯了很多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. 一個人的高三樓