zoukankan      html  css  js  c++  java
  • P2480 [SDOI2010]古代猪文

    P2480 [SDOI2010]古代猪文

    比较综合的一题
    前置:Lucas 定理crt

    求的是:

    [g^xmod 999911659, ext{其中}x=sum_{dmid n} binom{n}{d} ]

    由于这个(999911659)是质数,肯定于(g)互质,所以由欧拉定理很容易证明:

    [a^{varphi(p)}equiv 1pmod pRightarrow a^{kmod varphi(p)}equiv a^kpmod p ]

    那么可以得出:

    [g^xmod 999911659equiv g^{xmod varphi(999911659)}pmod {999911659} ]

    [g^xmod 999911659equiv g^{xmod 999911658}pmod {999911659} ]

    所以问题转换为求:

    [sum_{dmid n} binom{n}{d}mod 999911658 ]

    这种大组合数的问题考虑用 Lucas,但是模数太大,且不是质数
    所以考虑将它分解:(999911658=2 imes 3 imes 4679 imes 35617)
    那么,只需要对每一个质因数,求出(aequiv sum_{dmid n} binom{n}{d}mod p_i),然后再用 crt 合并就行了

    算的时候,枚举每一个(ile sqrt n),如果(imid n),则计算( binom{n}{i})( binom{n}{frac{n}{i}})加到答案里
    但是,在这种因数不能重复计算的时候,要:

    for(reg int i=1;i*i<=n;i++)
    

    而不是

    for(reg int i=1;i<=std::ceil(std::sqrt(n));i++)
    

    对于后一种,举个栗子:(lceilsqrt {420} ceil=21),但是如果(i)一直枚举到(21),就会在(i=20,i=21)的时候算两次(20,21)这两个因数,重复了,出现错误

    还有,因为每次的计算模数不同,所以要分别预处理

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<map>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	register int x=0;register int y=1;
    	register char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    const int prime[4]={2,3,4679,35617};
    int fac[40006],inv[40005];
    inline int power(int a,int b,int p){
    	int ret=1;
    	while(b){
    		if(b&1) ret=1ll*ret*a%p;
    		b>>=1;a=1ll*a*a%p;
    	}
    	return ret;
    }
    inline void pre(int n,int mod){
    	fac[0]=inv[0]=1;
    	for(reg int i=1;i<n;i++) fac[i]=(LL)fac[i-1]*i%mod;
    	inv[n-1]=power(fac[n-1],mod-2,mod);
    	for(reg int i=n-2;i;i--) inv[i]=(LL)inv[i+1]*(i+1)%mod;
    }
    inline int get_C(int n,int m,int mod){
    	//C(n,m)=n!/(m!*(n-m)!)
    	if(n<m) return 0;
    	return ((LL)fac[n]*inv[m]%mod)*inv[n-m]%mod;
    }
    inline int lucas(int n,int m,int mod){
    	if(n<m) return 0;
    	if(!n||!m) return 1;
    	return (LL)lucas(n/mod,m/mod,mod)*get_C(n%mod,m%mod,mod)%mod;
    }
    int main(){
    //	std::freopen("out.txt","w",stdout);
    	const int M=999911658;
    	int n=read(),g=read();
    	g%=(M+1);
    	if(!g) return std::puts("0"),0;
    	reg int ans=0,Mi,t;
    	for(reg int o=0;o<4;o++){
    		pre(prime[o],prime[o]);
    		reg int nowans=0;
    		for(reg int i=1;i*i<=n;i++)if(!(n%i)){
    			nowans=(nowans+lucas(n,i,prime[o]))%prime[o];
    			if(i*i!=n) nowans=((LL)nowans+lucas(n,n/i,prime[o]))%prime[o];
    		}
    //			std::printf("now ans = %d
    ",nowans);
    //			for(reg int i=0;i<prime[o];i++) std::printf("%d %d
    ",fac[i],inv[i]);
    		Mi=M/prime[o];
    		t=power(Mi,prime[o]-2,prime[o]);//t=Mi^{-1} mod prime[o]
    		ans=(ans+((LL)nowans*Mi%M*t%M))%M;
    	}
    	std::printf("%d",power(g,ans,M+1));
    	return 0;
    }
    
  • 相关阅读:
    Java操作redis
    Ajax & Json
    【转载】K8s-Pod时区与宿主时区时区同步
    【转载】Python中如何将字符串作为变量名
    【转载】python实现dubbo接口的调用
    机器学习避坑指南:训练集/测试集分布一致性检查
    机器学习深度研究:特征选择中几个重要的统计学概念
    机器学习数学基础:学习线性代数,千万不要误入歧途!推荐一个正确学习路线
    被 Pandas read_csv 坑了
    print('Hello World!')的新玩法
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/12675173.html
Copyright © 2011-2022 走看看