luoguP2480 [SDOI2010] 고대 돼지 문화

문제의 의미

요청이 고려되어야한다 : \ (G ^ {\ SUM \ limits_ {D | D ^ N-C_n}} \ % 999 911 659 \) .

찾은 중요 계수, 오일러 프로파일의 제 1 계수 정리 : \ (G ^ {\ SUM \ limits_ {D | D ^ N-C_n} \} % 999 911 658 \ % 999 911 659 \) .

사실, 우리는 물어 \ (\ SUM \ limits_ {D를 |} C_n는 N- ^ D \ % 999 911 658 \) , 신속하게 전력이 될 수 있습니다.

찾을 \ (999 911 658 \) 하지 소수, 결코 루카스 정리 수요와 조합의 수, 그래서 개방을 고려 \ (999 911 658 \) 와 것으로 확인 \ (2,3,4679,35617 \) .

따라서, 이들 네 가지 요건의 수가 하형 의미이다 \ (\ SUM \ limits_ {D | D ^ N-C_n} \) , 상기 제 1 가정 \ (I \) 판정 번째 \ (A_I \)

우리는 네 가지 형태로 발견 가지고 \ (X \ 당량 A_I \ pmod에 {p_i} \) (실제로 exLucas의 단순화 된 버전입니다) 답을 얻기 위해 중국 잉여 정리 병합을 사용하여 방정식을.

암호:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod1=999911659;
const ll mod2=999911658;
const int maxs=40010;
ll n,m;
ll a[5],prime[]={0,2,3,4679,35617};
ll fac[maxs][5],inv[maxs][5];
inline ll power(ll x,ll k,ll mod)
{
    ll res=1;
    while(k)
    {
        if(k&1)res=res*x%mod;
        x=x*x%mod;k>>=1;
    }
    return res;
}
inline ll C(ll n,ll m,ll op)
{
    if(m>n)return 0;
    return fac[n][op]*inv[n-m][op]%prime[op]*inv[m][op]%prime[op];
}
inline ll Lucas(ll n,ll m,ll op)
{
    if(!m)return 1;
    return C(n%prime[op],m%prime[op],op)*Lucas(n/prime[op],m/prime[op],op)%prime[op];
}
void exgcd(ll a,ll b,ll& x,ll& y)
{
    if(!b){x=1,y=0;return;}
    exgcd(b,a%b,x,y);
    ll z=x;x=y,y=z-(a/b)*y;
}
inline ll CRT()
{
    ll res=0;
    for(int i=1;i<=4;i++)
    {
        ll x,y,M=mod2/prime[i];
        exgcd(M,prime[i],x,y);
        x=(x%prime[i]+prime[i])%prime[i];
        res=(res+a[i]*x%mod2*M%mod2)%mod2;
    }
    return res;
}
int main()
{
    scanf("%lld%lld",&n,&m);
    if(m==mod1){puts("0");return 0;}
    for(int i=1;i<=4;i++)
    {
        fac[0][i]=1;
        for(int j=1;j<prime[i];j++)fac[j][i]=fac[j-1][i]*j%prime[i];
        inv[prime[i]-1][i]=power(fac[prime[i]-1][i],prime[i]-2,prime[i]);
        for(int j=prime[i]-1;j;j--)inv[j-1][i]=inv[j][i]*j%prime[i];
    }
    for(ll i=1;i*i<=n;i++)
    {
        if(n%i)continue;
        for(int j=1;j<=4;j++)
        {
            a[j]=(a[j]+Lucas(n,i,j))%prime[j];
            if(i*i!=n)a[j]=(a[j]+Lucas(n,n/i,j))%prime[j];
        }
    }
    printf("%lld",power(m,CRT(),mod1));
    return 0;
}

추천

출처www.cnblogs.com/nofind/p/11933166.html