2018.10.19每天認真做一道數學(數論)題之BZOJ 1951 [Sdoi2010]古代豬文【數論板子】【尤拉定理】【Lucas】【CRT】
阿新 • • 發佈:2018-11-08
由題意:
由於 是一個質數,我們接下來分兩類討論:
- ,顯然
-
,於是
,由尤拉定理得到:
注意到:
於是我們接下來我們列舉 ,即 的約數,用 求出 ,分別計算 對 取模的結果,我們記為
設
,則有:
由於 兩兩互質,我們可以通過剩餘定理求出
於是
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define sg string
#define ll long long
#define rel(i,x,y) for(ll i=(x);i<(y);i++)
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define red(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;
const ll N=1e5+5;
const ll Mod=999911659;
ll n,q,ans;
ll a[5],m[5]={0,2,3,4679,35617};
inline ll read() {
ll x=0;char ch=getchar();bool f=0;
while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?-x:x;
}
inline ll ksm(ll a,ll b,ll p) {
ll ret=1%p;
while(b) {
if(b&1) ret=ret*a%p;
b>>=1;a=a*a%p;
}
return ret;
}
ll C(ll a,ll b,ll p) {
ll A=1,B=1;
if(a<b) return 0;
else if(a==b) return 1;
if(b>a-b) b=a-b;
rel(i,0,b) {
A=A*(a-i)%p;
B=B*(b-i)%p;
}
return A*ksm(B,p-2,p)%p;
}
ll lucas(ll n,ll m,ll p) {
return m==0?1:C(n%p,m%p,p)*lucas(n/p,m/p,p)%p;
}
void exgcd(ll a,ll b,ll &gcd,ll &x,ll &y) {
if(b==0) {
x=1;y=0;gcd=a;return ;
}exgcd(b,a%b,gcd,x,y);
ll ret=x;x=y;y=ret-a/b*y;
}
void crt() {
ll mm=1;
rep(i,1,4) mm*=m[i];
rep(i,1,4) {
ll x,y,gcd;
ll mi=mm/m[i];
exgcd(mi,m[i],gcd,x,y);
ans=(ans+x*mi*a[i])%mm;
}
ans=(ans%mm+mm)%mm;
}
int main(){
n=read(),q=read();
if(q==999911659) {
puts("0");return 0;
}
ll s=sqrt(n);
rep(i,1,s) if(n%i==0) {
if(i*i!=n) {
rep(j,1,4) a[j]+=lucas(n,i,m[j])+lucas(n,n/i,m[j]);
} else {
rep(j,1,4) a[j]+=lucas(n,i,m[j]);
}
}
crt();
printf("%lld\n",ksm(q,ans,Mod));
return 0;
}