zoukankan      html  css  js  c++  java
  • uoj450 【集训队作业2018】复读机(生成函数,单位根反演)

    uoj450 【集训队作业2018】复读机(生成函数,单位根反演)

    uoj

    题解时间

    首先直接搞出单个复读机的生成函数 $ sumlimits_{ i = 0 }^{ k } [ d | i ] frac{ x^{ i } }{ i! } $ 。

    容易想到直接上单位根反演:

    [egin{aligned} sumlimits_{ i = 0 }^{ k } [ d | i ] frac{ x^{ i } }{ i! } & = sumlimits_{ i = 0 }^{ k } frac{ 1 }{ d } sumlimits_{ j = 0 }^{ d - 1 } omega_{ d }^{ ij } frac{ x^{ i } }{ i! } \ & = frac{ 1 }{ d } sumlimits_{ j = 0 }^{ d - 1 } sumlimits_{ i = 0 }^{ k } frac{ ( omega_{ d }^{ j } x )^{ i } }{ i! } \ & = frac{ 1 }{ d } sumlimits_{ j = 0 }^{ d - 1 } e^{ ( omega_{ d }^{ j } x )^{ i } } end{aligned} ]

    然后答案就是 $ [ x^{ n } ] ( frac{ 1 }{ d^{ k } } ( sumlimits_{ j = 0 }^{ d - 1 } e^{ omega_{ d }^{ j } x } )^{ k } ) $ 。

    由于 $ d le 3 $ ,所以直接大力二项式定理,时间复杂度 $ O( d k^{d-1} log{ k } ) $ 。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long lint;
    struct pat{int x,y;pat(int x=0,int y=0):x(x),y(y){}bool operator<(const pat &p)const{return x==p.x?y<p.y:x<p.x;}};
    template<typename TP>inline void read(TP &tar)
    {
    	TP ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){ret=ret*10+(ch-'0');ch=getchar();}
    	tar=ret*f;
    }
    template<typename TP,typename... Args>inline void read(TP& t,Args&... args){read(t),read(args...);}
    namespace RKK
    {
    const int N=500011;
    const int mo=19491001;
    const int g=7,om=18827933;
    void doadd(int &a,int b){if((a+=b)>=mo) a-=mo;}int add(int a,int b){return (a+=b)>=mo?a-mo:a;}
    void dodec(int &a,int b){doadd(a,mo-b);}int dec(int a,int b){return add(a,mo-b);}
    void domul(int &a,int b){a=1ll*a*b%mo;}int mul(int a,int b){return 1ll*a*b%mo;}
    int fpow(int a,int p){int ret=1;while(p){if(p&1) domul(ret,a);domul(a,a),p>>=1;}return ret;}
    int inv[N],fac[N],ifac[N];
    void init()
    {
    	inv[1]=1;for(int i=2;i<=500000;i++) inv[i]=mul(inv[mo%i],mo-mo/i);
    	for(int i=fac[0]=1;i<=500000;i++) fac[i]=mul(fac[i-1],i);
    	for(int i=ifac[0]=1;i<=500000;i++) ifac[i]=mul(ifac[i-1],inv[i]);
    }
    int C(int n,int m){if(n<m||n<0||m<0) return 0;return mul(fac[n],mul(ifac[n-m],ifac[m]));}
    int n,m,d,ans;
    int main()
    {
    	init();
    	read(n,m,d);
    	switch(d)
    	{
    	case 1:
    		ans=fpow(m,n);
    		break;
    	case 2:
    		for(int i=0;i<=m;i++) doadd(ans,mul(C(m,i),fpow(dec(i*2,m),n)));
    		break;
    	case 3:
    		for(int i=0;i<=m;i++)for(int j=0;i+j<=m;j++)
    			doadd(ans,mul(mul(C(m,i),C(m-i,j)),fpow(add(m-i-j,add(mul(om,i),mul(mul(om,om),j))),n)));
    		break;
    	}
    	domul(ans,fpow(inv[d],m));
    	printf("%d
    ",ans);
    	return 0;
    }
    }
    int main(){return RKK::main();}
    
  • 相关阅读:
    oracle 导入数据时提示只有 DBA 才能导入由其他 DBA 导出的文件
    oracle 常用语句
    android udp 无法收到数据 (模拟器中)
    android DatagramSocket send 发送数据出错
    AtCoder ABC 128E Roadwork
    AtCoder ABC 128D equeue
    AtCoder ABC 127F Absolute Minima
    AtCoder ABC 127E Cell Distance
    CodeForces 1166E The LCMs Must be Large
    CodeForces 1166D Cute Sequences
  • 原文地址:https://www.cnblogs.com/rikurika/p/13376760.html
Copyright © 2011-2022 走看看