版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/zzk_233/article/details/83474404
这是一道数论集合题
求式子,首先可以先用欧拉定理将式子降幂为指数mod (999911659-1)。
而对于指数可以在根号n的时间内枚举每个约数,对于每个约数求相应的组合数,可以用lucas定理来求解,
但是因为这个模数不是指数,所以把这个模数拆开,再用中国剩余定理合并就好了
注意的点是当g等于999911659时,这个定理不适用,但显然答案是0,所以要特判掉。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define mode 999911658
using namespace std;
typedef long long ll;
ll n,g,x,y;
ll mod[5]={0,2,3,4679,35617};
ll niv[5][40005],jc[5][40005],ans[5],tot;
void gett(int u)
{
niv[u][1]=1;
for(int i=2;i<mod[u];i++)
{
niv[u][i]=(mod[u]-mod[u]/i)*niv[u][mod[u]%i]%mod[u];
}
jc[u][0]=1;
for(int i=1;i<mod[u];i++)
{
jc[u][i]=jc[u][i-1]*i%mod[u];
}
niv[u][0]=1;
for(int i=1;i<mod[u];i++)
{
niv[u][i]=niv[u][i-1]*niv[u][i]%mod[u];
}
}
ll exgcd(ll a,ll b)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll r=exgcd(b,a%b);
ll t=x;
x=y;
y=t-a/b*x;
return r;
}
ll Lucas(ll x,ll y,int u)
{
if(x==0)return 1;
if(y%mod[u]<x%mod[u])return 0;
return Lucas(x/mod[u],y/mod[u],u)%mod[u]*jc[u][y%mod[u]]%mod[u]*niv[u][x%mod[u]]%mod[u]*niv[u][((y-x)%mod[u]+mod[u])%mod[u]]%mod[u];
}
ll crt(int u)
{
ll as=0;
for(int i=1;i<=4;i++)
{
ans[i]=Lucas(u,n,i);
ll gg=exgcd(mode/mod[i],mod[i]);
ans[i]/=gg;
x=(x%mod[i]+mod[i])%mod[i];
x*=ans[i]%mode;x%=mode;
as+=x*mode/mod[i]%mode;
as%=mode;
}
return as;
}
void ys(ll u)
{
for(ll i=1;i*i<=u;i++)
{
if(u%i==0)
{
tot+=crt(i)%mode;
tot%=mode;
if(i*i==u)continue;
tot+=crt(u/i)%mode;
tot%=mode;
}
}
}
ll ksm(ll x,ll y)
{
ll as=1;
while(y)
{
if(y%2==1)
{
as=as*x%(mode+1);
}
x=x*x%(mode+1);
y=y/2;
}
return as;
}
int main()
{
scanf("%lld%lld",&n,&g);
if(g==mode+1)
{
printf("0");
return 0;
}
for(int i=1;i<=4;i++)gett(i);
ys(n);
printf("%lld",ksm(g,tot)%(mode+1));
return 0;
}