• P5488 差分与前缀和


    P5488 差分与前缀和

    先看前缀和。

    首先有一个显然的递推:

    [sum_{k,i}=sum_{k,i-1}+sum_{k-1,i}\ sum_{0,i}=a_i ]

    按照套路考虑 (a_j)(sum_{k,i}) 的贡献。

    看看这个递推,不就是从 ((0,j)) 走到 ((k,i)) 这个点的方案数吗??直接 (inom{k+i-j}{k}) 即可。

    然后发现挂掉了。。。。。。。

    忽然发现 (sum_{0,i}) 不能转移到 (sum_{0,i+1}) 的!于是少了一步,应该是 (inom{k-1+i-j}{k-1})

    注意这个 (k) 太大了,但是是可以直接 (mod 998244353) 的。然后递推 (p_i=inom{k+i}{k}) 即可。

    发现 (a*p) 就是答案了。

    再考虑差分。

    之前见过一点生成函数内容。 (k) 阶差分就是乘上 ((1-x)^k) ,这东西二项式系数就是 ((-1)^iinom{k}{i})

    递推预处理 (p_i=(-1)^iinom{k}{i})(a*p) 就是答案了。

    const int N=100005;
    const int M=N<<2;
    #define mod 1004535809
    void fmod(int&x){x+=x>>31&mod,x-=mod,x+=x>>31&mod;}
    int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*n*res%mod;return res;}
    inline int exread(){
    	int x=0;char ch=getchar();
    	while(!isdigit(ch))ch=getchar();
    	while(isdigit(ch))x=(1ll*x*10+ch-'0')%mod,ch=getchar();
    	return x;
    }
    
    int rev[M],lg,lim;
    void init(const int&n){
    	for(lg=0,lim=1;lim<=n;lim<<=1,++lg);
    	for(int i=0;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
    }
    void NTT(int*a,int op){
    	int g=op?3:qpow(3,mod-2);
    	for(int i=0;i<lim;++i)if(i>rev[i])swap(a[i],a[rev[i]]);
    	for(int i=1;i<lim;i<<=1){
    		int wn=qpow(g,(mod-1)/(i<<1));
    		for(int j=0;j<lim;j+=i<<1){
    			int w0=1;
    			for(int k=0;k<i;++k,w0=1ll*w0*wn%mod){
    				const int X=a[j+k],Y=1ll*w0*a[i+j+k]%mod;
    				fmod(a[j+k]=X+Y),fmod(a[i+j+k]=X-Y+mod);
    			}
    		}
    	}
    	if(op)return;int ilim=qpow(lim,mod-2);
    	for(int i=0;i<lim;++i)a[i]=1ll*ilim*a[i]%mod;
    }
    
    int n,k,t,a[M],f[M];
    namespace solve1{
    signed main(){
    	f[0]=1;for(int i=1;i<n;++i)f[i]=1ll*f[i-1]*(k+i-1)%mod*qpow(i,mod-2)%mod;
    	init(n<<1),NTT(a,1),NTT(f,1);
    	for(int i=0;i<lim;++i)f[i]=1ll*a[i]*f[i]%mod;
    	NTT(f,0);
    	for(int i=0;i<n;++i)fmod(f[i]),printf("%d ",f[i]);
    	return 0;
    }
    
    }
    namespace solve2{
    signed main(){
    	f[0]=1;for(int i=1;i<n;++i)f[i]=-1ll*f[i-1]*(k-i+1)%mod*qpow(i,mod-2)%mod;
    	init(n<<1),NTT(a,1),NTT(f,1);
    	for(int i=0;i<lim;++i)f[i]=1ll*a[i]*f[i]%mod;
    	NTT(f,0);
    	for(int i=0;i<n;++i)fmod(f[i]),printf("%d ",f[i]);
    	return 0;
    }
    }
    signed main(){
    	n=read(),k=exread(),t=read();
    	for(int i=0;i<n;++i)a[i]=read();
    	if(!t)solve1::main();else solve2::main();
    	return 0;
    }
    

    大概是我人傻常数大的缘故,不知道为啥别人跑的这么快。。。

  • 相关阅读:
    配置postgres9.3间的fdw——实现不同postgres数据库间的互访问
    linux安装配置postgres及使用dblink
    一次“峰回路转”的troubleshooting经历
    10分钟内把永远跑不完的存储过程变为2秒跑完
    C++ friend关键字
    每天学点Linux命令之 vi 命令
    Shell
    九大排序算法及其实现- 插入.冒泡.选择.归并.快速.堆排序.计数.基数.桶排序.堆排序
    到位
    【LeetCode】-- 260. Single Number III
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14191414.html
Copyright © 2020-2023  润新知