• 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();}
    
  • 相关阅读:
    pytest扫盲21--pytest-assume多重效验插件
    pytest扫盲20--HTML报告
    pytest扫盲19--pytest重运行机制
    pytest扫盲18--配置文件pytest.ini
    pytest扫盲17--自定义命令行参数
    pytest扫盲16--某个用例失败后,关联的用例标记为xfail
    pytest扫盲15--skip跳过用例
    pytest扫盲14--pytest.raises()函数文档及在参数化中处理异常
    pytest扫盲13--遇到异常的两种处理方式及断言异常
    【CF】CF1430_G Yet Another DAG Problem_最小割/网络流/状压dp
  • 原文地址:https://www.cnblogs.com/rikurika/p/13376760.html
Copyright © 2020-2023  润新知