题解
%%%
- 其实就是个板子( \(exlucas\) )。
- 一开始以为直接用 \(lucas\) 就可以过了,但是显然不是这样的。这道题需要用到欧拉定理和 \(exlucas\) ( \(lucas+crt\) )。
- 首先质数 \(999911659\) 的欧拉函数是 \(999911658\) 。因为欧拉定理,所以 \(\large a^{999911658} \equiv 1 \pmod{999911659}\) 。
- 如果我们直接用 \(lucas\) ,那么模数就像没有一样,因此需要减小模数。
- 因此减小模数是势在必得的。将 \(999911658\) 分解质因数,得到 \(999911658=2 \times 3 \times 4679 \times 35617\) 。
- 对于每一个质因数,分别进行 \(lucas\) ,事实上可以对阶乘进行预处理,但似乎有些麻烦,现算也是不会超时的。
- 从 \(1\) 开始,对每个因子(假设为 \(i\) )和 \(\dfrac{n}{i}\) 进行 \(lucas\) ,算出模每个质因数意义下的情况数,一直到 \(\sqrt{n}\) 。算出每个结果后,进行 \(crt\) 。 (由于模数都是质数,一定互质。所以 \(excrt\) 与 \(crt\) 一个效果),最后算出最小的结果后,直接快速幂算出来即可。
代码
#include<bits/stdc++.h>
#define ls (p<<1)
#define rs (p<<1|1)
#define endl '\n'
#define N (10000010)
#define int long long
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<25;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char end){pit(x);*o++=end;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;
int n,m,t,P;
int x,y,k,ans,g;
int mod[N],a[N];
int len,prime[700010];//,phi[N];//线性筛欧拉函数
bitset<N>vis;
int jc[N];
long long inv[N];//乘法逆元
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}
inline void swap(int &x,int &y){int tmp=x;x=y;y=tmp;}
int e[N],siz[N];
long long qpow(long long x,int b,int P=P)
{
long long ans=1;
for(;b;b>>=1){if(b&1)ans=(ans*x)%P;x=(x*x)%P;}
return ans;
}//O(log(b))
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int exgcd(int a,int b,int &x,int &y)
{
if(!b){x=1,y=0;return a;}
int d=exgcd(b,a%b,y,x);
y-=(a/b*x);
return d;
}//O(max(a,b))
int ola(int n)
{
int ans=n;
for(int i=2;i*i<=n;++i)
{
if(n%i==0)ans=ans/i*(i-1);
for(;n%i==0;n/=i);
}
if(n>1)ans=ans/n*(n-1);
return ans;
}//O(sqrt(n))
void eular(int n)//欧拉筛
{
//memset(vis,0,sizeof(vis));
//phi[1]=1;
for(int i(2);i<=n;++i)
{
if(!vis[i])
prime[++len]=i;//,phi[i]=(i-1);
for(int j(1);j<=len&&i*prime[j]<=n;++j)
{
vis[i*prime[j]]=1;
/*
if(!(i%prime[j]))
{phi[i*prime[j]]=(phi[i]*prime[j]);break;}
else phi[i*prime[j]]=(phi[i]*(prime[j]-1));
*/
}
}
}//O(n)
void niyuan1(int n,int P=P)//乘法逆元
{
inv[1]=1;
for(int i(2);i<=n;++i)inv[i]=((P-P/i)*inv[P%i])%P;
}//O(n)
int inv_it(int a,int P=P)//O(log(a))
{
int d(exgcd(a,P,x,y));
return(x%P+P)%P;
}
int C(int n,int m,int P=P)
{
if(m>n)return 0;
int a(1),b(1);
for(int i(n-m+1);i<=n;++i)a=(a*i)%P;
for(int i(2);i<=m;++i)b=(b*i)%P;
return (a*qpow(b,P-2,P))%P;
}
int lucas(int n,int m,int P=P)
{return (!m)?1:(C(n%P,m%P,P)*lucas(n/P,m/P,P))%P;}
int excrt(int n)//扩展中国剩余定理
{
int mul(mod[1]);ans=a[1];
int x,y,c,d;
for(int i(2);i<=n;++i)
{
x=y=0;
c=(a[i]-ans%mod[i]+mod[i])%mod[i];
d=exgcd(mul,mod[i],x,y);
if(!(c%d))
ans+=(((x+mod[i])%mod[i])*(c/d)%mod[i])*mul,
mul=mul*mod[i]/gcd(mul,mod[i]),
ans%=mul;
else return -1;
}
return ans%mul;
}
void solve_C(int n,int m)
{
for(int i(1);i<=4;++i)
a[i]=(a[i]+lucas(n,m,mod[i]))%mod[i];
}
void init()
{
n=read(),g=read();P=999911659;
if(!(g%P))puts("0"),exit(0);
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
init();
mod[1]=2,mod[2]=3,mod[3]=4679,mod[4]=35617;
int nn(sqrt(n));
for(int i(1);i<=nn;++i)
if(!(n%i))
solve_C(n,i),solve_C(n,n/i);
/*
for(int i(1);i<nn;++i)
if(!(n%i))
a[1]=(a[1]+lucas(n,i,2)+lucas(n,n/i,2))%2,
a[2]=(a[2]+lucas(n,i,3)+lucas(n,n/i,3))%3,
a[3]=(a[3]+lucas(n,i,4679)+lucas(n,n/i,4679))%4679,
a[4]=(a[4]+lucas(n,i,35617)+lucas(n,n/i,35617))%35617;
write(qpow(g,excrt(4),P),'\n');
flush();
return 0;
}
//999911658=2*3*4679*35617
//n=24 : 227655187 ^ 3587174 == 268407382 (mod 999911659)