• 「loj#6261」一个人的高三楼


    题目

    显然存在一个这样的柿子

    [S^{(k)}_i=sum_{j=1}^iS^{(k-1)}_j ]

    我们可以视为(S^{(k)})就是由(S^{(k-1)})卷上一个长度为(n)全是(1)的多项式得来的

    设这样的全是(1)的多项式为(A),给出的多项式为(F)我们要求的就是(F imes A^k)

    发现(k)非常大,我们可以考虑把我们要求的东西变成(F imes exp(kln A)),复杂度(O(nlog n))

    之后我就本着复习的想法去写了多项式(exp),之后自闭了

    好歹我最后写出来了

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int maxn=262144+5;
    const int mod=998244353;
    const int G[2]={3,(mod+1)/3};
    int len,n,k,a[maxn],b[maxn],c[maxn],d[maxn],inv[maxn];
    int g[maxn],H[maxn],K[maxn],C[maxn],rev[maxn],T[maxn];
    inline int ksm(int a,int b) {
    	int S=1;
    	while(b) {if(b&1) S=1ll*S*a%mod;b>>=1;a=1ll*a*a%mod;}
    	return S;
    }
    inline int getPow() {
        int x=0;char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(10ll*x+c-48)%mod,c=getchar();
        return x;
    }
    inline void NTT(int *f,int o) {
    	for(re int i=0;i<len;i++) if(i<rev[i]) std::swap(f[i],f[rev[i]]);
    	for(re int i=2;i<=len;i<<=1) {
    		int ln=i>>1,og1=ksm(G[o],(mod-1)/i);
    		for(re int l=0;l<len;l+=i) {
    			int t,og=1;
    			for(re int x=l;x<l+ln;++x) {
    				t=1ll*f[x+ln]*og%mod;
    				f[x+ln]=(f[x]-t+mod)%mod;
    				f[x]=(f[x]+t)%mod;
    				og=1ll*og*og1%mod;
    			}
    		}
    	}
    	if(!o) return;
    	for(re int i=0;i<len;i++) f[i]=1ll*f[i]*inv[len]%mod;
    }
    void Inv(int n,int *A,int *B) {
    	if(n==1) {B[0]=ksm(A[0],mod-2);return;}
    	Inv((n+1)>>1,A,B);
    	for(re int i=0;i<n;i++) g[i]=A[i];
    	for(re int i=n;i<len;i++) g[i]=0;
    	len=1;while(len<n+n) len<<=1;
    	for(re int i=0;i<len;i++) rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
    	NTT(g,0),NTT(B,0);
    	for(re int i=0;i<len;i++) B[i]=(2ll*B[i]-1ll*g[i]*B[i]%mod*B[i]%mod+mod)%mod;
    	NTT(B,1);for(re int i=n;i<len;i++) B[i]=0;
    }
    void Ln(int n,int *A,int *B) {
    	memset(T,0,sizeof(T));memset(B,0,sizeof(B));
    	for(re int i=1;i<n;i++) T[i-1]=1ll*i*A[i]%mod;
    	memset(C,0,sizeof(C));Inv(n,A,C);
    	len=1;while(len<n+n) len<<=1;
    	for(re int i=0;i<len;i++) rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
    	NTT(C,0),NTT(T,0);
    	for(re int i=0;i<len;i++) C[i]=1ll*C[i]*T[i]%mod;
    	NTT(C,1);for(re int i=1;i<n;i++) B[i]=1ll*C[i-1]*inv[i]%mod;
    }
    void Exp(int n,int *A,int *B) {
    	if(n==1) {B[0]=1;return;}
    	Exp((n+1)>>1,A,B);Ln(n,B,K);
    	len=1;while(len<n+n) len<<=1;
    	for(re int i=0;i<n;i++) K[i]=(A[i]-K[i]+mod)%mod;
    	for(re int i=n;i<len;i++) K[i]=0;K[0]++;
    	for(re int i=0;i<len;i++) rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
    	NTT(K,0),NTT(B,0);
    	for(re int i=0;i<len;i++) B[i]=1ll*B[i]*K[i]%mod;
    	NTT(B,1);for(re int i=n;i<len;i++) B[i]=0;
    }
    int main() {
    	inv[1]=1;
    	for(re int i=2;i<maxn;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    	n=read();k=getPow();
    	for(re int i=0;i<n;i++) a[i]=read();
    	for(re int i=0;i<n;i++) b[i]=1;
    	Ln(n,b,c);
    	for(re int i=0;i<n;i++) c[i]=1ll*c[i]*k%mod;
    	Exp(n,c,d);
    	len=1;while(len<n+n) len<<=1;
    	for(re int i=0;i<len;i++) rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
    	NTT(d,0),NTT(a,0);
    	for(re int i=0;i<len;i++) a[i]=1ll*a[i]*d[i]%mod;
    	NTT(a,1);for(re int i=0;i<n;i++) printf("%d
    ",a[i]);
    	return 0;
    }
    

    之后就获得了(20pts)的好成绩,这个时候才提醒我们时限只有(200ms)

    我们考虑到(A)这个多项式全是(1)肯定有一些奇妙的性质啊

    考虑(A^k(i))的组合意义,不就是相当于把(i)个球分到了(k)个盒子里,允许有空的方案数吗,根据经典的插板法,我们知道(A^k(i)=inom{i+k-1}{k-1})

    所以我们现在就不需要把(exp)了,直接用组合意义算出来之后去和(F)卷积就好了

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int maxn=262144+5;
    const int mod=998244353;
    const int G[2]={3,(mod+1)/3};
    inline int getPow() {
        int x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(10ll*x+c-48)%mod,c=getchar();
        return x;
    }
    inline int ksm(int a,int b) {
    	int S=1;while(b) {if(b&1) S=1ll*S*a%mod;b>>=1;a=1ll*a*a%mod;}return S;
    }
    int n,len,rev[262144+5],k;
    int a[262144+5],inv[262144+5],b[262144+5];
    inline void NTT(int *f,int o) {
    	for(re int i=0;i<len;i++) if(i<rev[i]) std::swap(f[i],f[rev[i]]);
    	for(re int i=2;i<=len;i<<=1) {
    		int ln=i>>1,og1=ksm(G[o],(mod-1)/i);
    		for(re int l=0;l<len;l+=i) {
    			int t,og=1;
    			for(re int x=l;x<l+ln;++x) {
    				t=1ll*og*f[x+ln]%mod;
    				f[x+ln]=(f[x]-t+mod)%mod;
    				f[x]=(f[x]+t)%mod;
    				og=1ll*og*og1%mod;
    			}
    		}
    	}
    	if(!o) return;
    	for(re int i=0;i<len;i++) f[i]=1ll*f[i]*inv[len]%mod;
    }
    int main() {
    	n=read();k=getPow();
    	for(re int i=0;i<n;i++) a[i]=read();
    	b[0]=1;int now=k;inv[1]=1;
    	len=1;while(len<n+n) len<<=1;
    	for(re int i=0;i<len;i++) rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
    	for(re int i=2;i<=len;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    	for(re int i=1;i<n;i++) b[i]=1ll*b[i-1]*inv[i]%mod*now%mod,now++,now=now%mod;
    	NTT(b,0),NTT(a,0);
    	for(re int i=0;i<len;i++) b[i]=1ll*a[i]*b[i]%mod;
    	NTT(b,1);for(re int i=0;i<n;i++) printf("%d
    ",b[i]);
    	return 0;
    }
    
  • 相关阅读:
    LeetCode 1245. Tree Diameter
    LeetCode 1152. Analyze User Website Visit Pattern
    LeetCode 1223. Dice Roll Simulation
    LeetCode 912. Sort an Array
    LeetCode 993. Cousins in Binary Tree
    LeetCode 1047. Remove All Adjacent Duplicates In String
    LeetCode 390. Elimination Game
    LeetCode 1209. Remove All Adjacent Duplicates in String II
    LeetCode 797. All Paths From Source to Target
    LeetCode 1029. Two City Scheduling
  • 原文地址:https://www.cnblogs.com/asuldb/p/10806135.html
Copyright © 2020-2023  润新知