Solution [SDOI2010]古代猪文
题目大意:给定(G),(n),求(G^{sum_{d mid n}C_n^d} ; mod;999911659)
欧拉定理,卢卡斯定理,EXCRT
分析:
我们发现问题的关键在于指数,然后答案可以用快速幂计算
首先我们观察模数,写个小程序发现(999911659)是个质数,于是我们可以用欧拉定理把指数缩小
若(gcd(a,p)=1),有(a^b equiv a^{b;mod;phi(p)};mod;p)
如果你(95)的话不妨加一个特判
好像也可以扩展欧拉定理不过哪儿那么麻烦
然后我们要求(sum_{d mid n}C_n^d ; mod;999911658)
(n)的所有约数我们可以(O(sqrt{n}))枚举,不用(O(n))因为约数成对出现
然后(C_n^d ; mod;999911658)这玩意儿可以扩展卢卡斯定理,但是这个模数比较特殊。我怀疑出题人是精心选取过的
(999911658=2 imes 3 imes 4679 imes 35617)
它有(4)个质因子并且指数都为(1)
我们可以分别对上述(4)个质因子取膜,EXCRT合并即可
//2 * 3 * 4679 * 35617
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxp = 36000;
ll qpow(ll a,ll b,ll mod){
a %= mod;
ll res = 1,base = a;
while(b){
if(b & 1)res = (res * base) % mod;
base = (base * base) % mod;
b >>= 1;
}
return res;
}
ll gcd(ll a,ll b){return !b ? a : gcd(b,a % b);}
ll lcm(ll a,ll b){return a / gcd(a,b) * b;}
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){
x = 1,y = 0;
return a;
}
ll res = exgcd(b,a % b,y,x);
y -= (a / b) * x;
return res;
}
ll mul(ll a,ll b,ll p){return (a * b) % p;}
struct Lucas{
ll fac[maxp],inv[maxp],p;
inline void init(ll x){
p = x,fac[0] = 1,inv[0] = qpow(fac[0],p - 2,p);
for(int i = 1;i <= p;i++)
fac[i] = (fac[i - 1] * i) % p,inv[i] = qpow(fac[i],p - 2,p);
}
inline ll C(ll n,ll m){
return m > n ? 0 : mul(fac[n],mul(inv[m],inv[n - m],p),p);
}
inline ll lucas(ll n,ll m){
return !m ? 1 : (lucas(n / p,m / p) * C(n % p,m % p)) % p;
}
}lucas[8];
ll n,base,exp,b[8],m[8] = {0,2,3,4679,35617};
inline ll excrt(){
ll M = m[1],res = b[1];
for(int i = 2;i <= 4;i++){
ll t,k,s = ((b[i] - res) % m[i] + m[i]) % m[i];
ll r = exgcd(M,m[i],t,k);
if(s % r)return -1;
t = mul(t,s / r,m[i] / r);
res += t * M;
M = lcm(M,m[i]);
res = (res % M + M) % M;
}
return res;
}
int main(){
scanf("%lld %lld",&n,&base);
if(!(base % 999911659))return printf("0
"),0;
for(int i = 1;i <= 4;i++)lucas[i].init(m[i]);
for(int i = 1;i * i <= n;i++)
if(!(n % i))
for(int k = 1;k <= 4;k++){
b[k] += lucas[k].lucas(n,i);
if(i != n / i)b[k] += lucas[k].lucas(n,n / i);
}
exp = excrt();
printf("%lld
",qpow(base,exp,999911659));
return 0;
}