做这个题大概需要直到以下姿势:快速幂,费马小定理,卢卡斯定理,中国剩余定理。(大概也就这些
题目大概是让求
g∑d|nCdnmodp
然后根据费马小定理原式
=g∑d|nCdnmod(p?1)modp
然后也就是要求指数上的这个东西 ∑d|nCdnmod(p?1)
然后p?1还不是质数。。需要分解成质因子然后用中国剩余定理合并,然后还要求组合数还要卢卡斯定理,最后特判一下g=p的情况
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define ll long long
#define mod 999911659 //2 3 4679 35617
#define N 100001
using namespace std;
int sc()
{
int i=0,f=1; char c=getchar();
while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();}
while(c>=‘0‘&&c<=‘9‘)i=i*10+c-‘0‘,c=getchar();
return i*f;
}
ll ans[4],fac[4][35666],inv[4][35666],p[4]={2,3,4679,35617};
ll n,g,a;
void pre()
{
for(int i=0;i<4;i++)
{
fac[i][0]=inv[i][0]=fac[i][1]=inv[i][1]=1;
for(int j=2;j<p[i];j++)
fac[i][j]=fac[i][j-1]*j%p[i],
inv[i][j]=inv[i][p[i]%j]*(p[i]-p[i]/j)%p[i];
for(int j=2;j<p[i];j++)
inv[i][j]=inv[i][j]*inv[i][j-1]%p[i];
}
}
ll C(ll n,ll m,int i)
{
if(n<m)return 0;
if(n<p[i]&&m<p[i])return fac[i][n]*inv[i][m]*inv[i][n-m]%p[i];
return C(n/p[i],m/p[i],i)*C(n%p[i],m%p[i],i)%p[i];
}
void solve(ll m)
{
for(int i=0;i<4;i++)
ans[i]=(ans[i]+C(n,m,i))%p[i];
}
void ex_gcd(ll x,ll y,ll &a,ll &b)
{
if(x==0){a=0,b=1;return;}
ex_gcd(y%x,x,b,a);
a-=b*(y/x);
}
int cal(ll x,int y)
{
ll ans=1;
for(;y;x=x*x%mod,y>>=1)
if(y&1)ans=ans*x%mod;
return ans;
}
int main()
{
pre();n=sc(),g=sc();a=sqrt(n);
if(g==mod){puts("0");return 0;}
for(int i=1;i<=a;i++)
if(n%i==0)
{
solve(i);
if(i*i!=n)solve(n/i);
}
for(int i=0;i<3;i++)
{
ll p1=p[i],p2=p[i+1],k1,k2;
p[i+1]=p[i+1]*p[i];
ex_gcd(p1,p2,k1,k2);
k1=k1%p2*(ans[i+1]-ans[i]);
ans[i+1]=(k1*p1+ans[i])%p[i+1];
}
printf("%d\n",cal(g,(ans[3]+p[3])%p[3]));
return 0;
}
时间: 2024-10-14 08:05:42