zoukankan      html  css  js  c++  java
  • [HEOI2016/TJOI2016] 求和

    推式子

    [f(n)=sum_{i=0}^nsum_{j=0}^iS(i,j) imes 2^j imes (j!)\ =sum_{i=0}^nsum_{j=0}^nS(i,j) imes 2^j imes (j!)=sum_{i=0}^n2^i imes (i!)sum_{j=0}^n S(j,i) ]

    注意到

    [S(n,m)=frac{1}{m!}sum_{i=0}^m(-1)^iC(m,i)(m-i)^n\ =sum_{i=0}^mfrac{(-1)^i imes (m-i)^n}{i! imes (m-i)!} ]

    带入得

    [f(n)=sum_{i=0}^n2^i imes i!sum_{j=0}^nsum_{k=0}^ifrac{(-1)^k imes(i-k)^j}{k! imes (i-k)!}\ =sum_{i=0}^n2^i imes i!sum_{k=0}^ifrac{(-1)^k}{k!}frac{sum_{j=0}^n(i-k)^j}{(i-k)!}\ ]

    注意,其中的(0^0=1)而非“未定义的操作”:离散、计数问题大都如此,可以参考讨论。然后就是很显然的卷积。

    #include <bits/stdc++.h>
    #define ll long long 
    using namespace std;
    
    const int N=4e5+10;
    const int mod=998244353;
    
    inline int qpow(ll x,ll y) {
    	int c=1;
    	for(; y; y>>=1,x=x*x%mod) if(y&1) c=x*c%mod;
    	return c;
    }
    int p,pl,rev[N];
    inline void ntt_init(int sum) {
    	for(p=1,pl=0; p<sum;) p<<=1,pl++;
    	for(int i=0; i<p; ++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(pl-1));
    }
    inline void ntt(int*a,int tp) {
    	for(int i=0; i<p; ++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
    	for(int m=1; m<p; m<<=1) {
    		ll wm=qpow(3,(mod-1)/(m<<1)); if(tp<0) wm=qpow(wm,mod-2);
    		for(int i=0; i<p; i+=(m<<1)) { ll w=1,tmp;
    			for(int j=0; j<m; ++j,w=w*wm%mod) {
    				tmp=w*a[i+j+m]%mod;
    				a[i+j+m]=(a[i+j]-tmp+mod)%mod;
    				a[i+j]=(a[i+j]+tmp)%mod;
    			}
    		}
    	}
    	if(tp<0) {
    		ll tmp=qpow(p,mod-2);
    		for(int i=0; i<p; ++i) a[i]=tmp*a[i]%mod;
    	}
    }
    int n,f[N],g[N];
    ll fc[N],fv[N];
    
    int main() {
    	scanf("%d",&n);
    	fc[0]=fc[1]=fv[0]=fv[1]=1;
    	for(int i=2; i<=n; ++i) fv[i]=fv[mod%i]*(mod-mod/i)%mod;
    	for(int i=2; i<=n; ++i) fv[i]=fv[i-1]*fv[i]%mod,fc[i]=fc[i-1]*i%mod;
    	f[0]=1,f[1]=mod-1,g[0]=1,g[1]=n+1;
    	for(int i=2; i<=n; ++i) {
    		f[i]=fv[i]*((i&1)?mod-1:1)%mod;
    		g[i]=fv[i]*((qpow(i,n+1)-1+mod)%mod)%mod*qpow(i-1,mod-2)%mod;
    	}
    	//for(int i=0; i<=n; ++i) printf("%d ",f[i]); printf("
    ");
    	//for(int i=0; i<=n; ++i) printf("%d ",g[i]); printf("
    ");
    	
    	ntt_init(n+n+2);
    	ntt(f,1); ntt(g,1);
    	//for(int i=0; i<p; ++i) printf("%d ",f[i]); printf("
    ");
    	//for(int i=0; i<p; ++i) printf("%d ",g[i]); printf("
    ");
    	
    	for(int i=0; i<p; ++i) f[i]=1LL*f[i]*g[i]%mod;
    	ntt(f,-1); ll P=1,sum=0;
    	for(int i=0; i<=n; ++i) {
    		sum=(sum+P*fc[i]%mod*f[i]%mod)%mod;
    		P=P*2%mod;
    	}
    	printf("%lld
    ",sum);
    	return 0;
    }
    

    写代码是别把p和mod弄混了……

  • 相关阅读:
    图片尺寸批量resize的matlab并行代码
    Java使用QRCode.jar生成与解析二维码
    MySQL求两表的差集(非交集)
    sql笔记
    Oracle创建表空间创建用户授权
    身份证前6位地址码+码表+MySQL
    Jenkins时区设置为北京时间
    Oracle 使用MERGE INTO 语句 一条语句搞定新增编辑
    Oracle dd-m月-yy转yyyy-mm-dd
    docker 使用笔记
  • 原文地址:https://www.cnblogs.com/nosta/p/10991862.html
Copyright © 2011-2022 走看看