P2480 [SDOI2010]古代猪文(lucas定理)

P2480 [SDOI2010]古代猪文(lucas定理)

题目链接:传送门

思路: 题目其实就是求 G ∑ d ∣ n C ( n , d ) % 999911659 ​ G^{\sum_{d|n}C(n,d)} \%999911659​ GdnC(n,d)%999911659的值,因为999911659是素数,我们我们可以用欧拉定理缩小幂次让原方程变为 G ∑ d ∣ n C ( n , d ) % ( 999911658 ) % 999911659 ​ G^{\sum_{d|n}C(n,d)\%(999911658)} \%999911659​ GdnC(n,d)%(999911658)%999911659,但是n太大,求幂次中的 ∑ d ∣ n C ( n , d ) % 999911658 ​ \sum_{d|n}C(n,d)\%999911658​ dnC(n,d)%999911658的值就不太现实,所以我们可以考虑将999911658分解素因子 2 , 3 , 4679 , 35617 ​ 2, 3,4679,35617​ 2,3,4679,35617的乘积,然后分别求 ∑ d ∣ n C ( n , d ) % 2 ​ \sum_{d|n}C(n,d)\%2​ dnC(n,d)%2 ∑ d ∣ n C ( n , d ) % 3 ​ \sum_{d|n}C(n,d)\%3​ dnC(n,d)%3 ∑ d ∣ n C ( n , d ) % 4679 ​ \sum_{d|n}C(n,d)\%4679​ dnC(n,d)%4679 ∑ d ∣ n C ( n , d ) % 35617 ​ \sum_{d|n}C(n,d)\%35617​ dnC(n,d)%35617。然后用CRT合并即可。

现在问题转化为大组合数取余小质数,此时我们可以使用 l u c a s ​ lucas​ lucas定理:

C ( a , b ) % p = C ( a % p , b % p ) ∗ C ( a / p , b / p ) % p C(a,b)\%p=C(a\%p,b\%p)*C(a/p,b/p)\%p C(a,b)%p=C(a%p,b%p)C(a/p,b/p)%p

就可以求出来了。

不过需要额外特判 G G G 999911659 999911659 999911659的倍数的情况。

代码

#include
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N=1e5+100;
const int inf=0x3f3f3f3f;
ll fac[N],tf;//因子
void dps_fac(ll n)//分解n的所有因子
{
    tf=0;
    for(int i=1;i*i<=n;++i){
        if(n%i==0){
            fac[tf++]=i;
            if(n/i!=i) fac[tf++]=n/i;
        }
    }
}
ll pf[20],tp;//素因子
void dps_p(ll n)//分解n的素因子
{
    tp=0;
    for(ll i=2;i*i<=n;++i){
        while(n%i==0){
            pf[tp++]=i;
            n/=i;
        }
    }
    if(n!=1) pf[tp++]=n;
}
ll qpow(ll a,ll b,ll p)
{
    if( a <= 0) return 0;
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%p;
        a=a*a%p;
        b>>=1;
    }
    return ans;
}
ll f[40005];//n!%mod
void init(ll mod)
{
    f[0]=1;
    for(int i=1;i<=36000;++i) f[i]=(f[i-1]*i)%mod;
}
ll C(ll n,ll m,ll p)//要求:预处理mod p的阶乘f[]
{
    if(n>n>>g;
    if(g%mod==0){
        cout<<0<

你可能感兴趣的:(#,数论杂项)