洛谷杂题
[SDOI2010]古代猪文
良心题,一题考了好几个数论知识
题意:求 \(G^{\sum\limits_{d|n}\dbinom{n}{d} }\%999911659\) 的值。
思路:
由欧拉定理可将问题转换为:\(\sum\limits_{d|n}\dbinom{n}{d}\%999911658\) 的值。
质数这么大,无法直接使用卢卡斯定理计算组合数。
考虑将 \(999911658\) 分解质因数,拆成 \(2\) ,\(3\) ,\(4679\) ,\(35617\) 四个质数。
对它们分别求出 \(\sum\limits_{d|n}\dbinom{n}{d}\) 模意义的值,设为 \(x1\) ,\(x2\) ,\(x3\) ,\(x4\) 。
可列方程组:
\[\begin{cases}
ans\equiv x1&\mod 2\\
ans\equiv x2&\mod 3\\
ans\equiv x3&\mod 4679\\
ans\equiv x4&\mod 35617
\end{cases}
\]
用 CRT 求解方程组,随后快速幂即可。
\(Code:\)
#include <bits/stdc++.h>
#define int long long
#define rgi register int
using namespace std;
const int M=1e5+7,inf=1e9+7,modd=999911658;
inline int read(){
int w=0,r=1;char c=getchar();
while(!(isdigit(c)||c=='-'))c=getchar();
if(c=='-')r=-1,c=getchar();
while(isdigit(c))w=w*10+c-'0',c=getchar();
return w*r;
}
int n,g,d[M],tot,an[M];
int ksm(int x,int y,int m){
int ans=1;
while(y){
if(y&1)ans=ans*x%m;
x=x*x%m;
y>>=1;
}
return ans;
}
int pri[4]={2,3,4679,35617},jc[M],jcinv[M],p;
void gitgud(int p){
jc[0]=1;
for(int i=1;i<=p;i++)jc[i]=jc[i-1]*i%p;
}
int C(int n,int m){
if(n<0||n<m)return 0;
if(n<p&&m<p)return jc[n]*ksm(jc[m],p-2,p)%p*ksm(jc[n-m],p-2,p)%p;
return C(n%p,m%p)*C(n/p,m/p)%p;
}
int res;
void CRT(){
res=0;
for(int i=0;i<4;i++)res=(res+an[i]*(modd/pri[i])%modd*ksm(modd/pri[i],pri[i]-2,pri[i]))%modd;
}
signed main(){
gitgud(100000);
n=read(),g=read();
if(g%(modd+1)==0){
printf("0\n");
return 0;
}
for(int cnt=0;cnt<4;cnt++){
p=pri[cnt];
gitgud(p);
int ret=0;
for(int i=1;i*i<=n;i++){
if(n%i==0){
an[cnt]=(an[cnt]+C(n,i))%p;
if(n!=i*i)an[cnt]=(an[cnt]+C(n,n/i))%p;
}
}
}
CRT();
printf("%lld\n",ksm(g,res,modd+1));
return 0;
}
/*
4 2
*/

浙公网安备 33010602011771号