欧拉定理(Euler theorem)
费马小定理(Fermat's little theorem)
威尔逊定理(Wilson theorem)
一个例子:
POJ 1845 Sumdiv
http://poj.org/problem?id=1845
大意:求解A^B的因子和,输出模9901的结果。
分析:设N分解成:,则 那么问题的结果就是:
于是这涉及到逆元,还可用费马小定理降幂。不过还有陷阱。。(此题原来也做过,曾经就因为不知道WA在哪里,改成了二分递归思路:http://blog.csdn.net/thearcticocean/article/details/48029837)
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long LL; const LL N=5e5+10,mod=9901; LL fac[N],cnt; bool vis[N]; void getfac(){ for(LL i=2;i<N;i++){ if(!vis[i]) fac[cnt++]=i; for(LL j=0;j<cnt&&fac[j]*i<N;j++){ vis[i*fac[j]]=1; if(i%fac[j]==0) break; } } } LL sta[N],pow[N],top; void solve(LL x){ memset(pow,0,sizeof(pow)); top=0; for(LL i=0;i<cnt&&fac[i]<=x;i++){ //i<cnt if(x%fac[i]==0){ sta[top]=fac[i]; while(x%fac[i]==0){ x/=fac[i]; pow[top]++; } top++; } } if(x>1){ sta[top]=x; pow[top]++; top++; } } void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y){ if(b==0){ d=a; x=1; y=0; return ; } ex_gcd(b,a%b,d,x,y); LL t=x; x=y; y=t-a/b*y; } LL power(LL a,LL p){ a=a%mod; LL ans=1; p=p%(mod-1); // 费马小定理 while(p){ if(p&1) ans=ans*a%mod; a=a*a%mod; p>>=1; } return ans; } int main() { //freopen("cin.txt","r",stdin); getfac(); LL A,B; while(cin>>A>>B){ if(A==0){ puts("0"); // 在这里 0^0=0 continue; } if(B==0){ puts("1"); continue; } solve(A); LL ans=1; for(LL i=0;i<top;i++){ LL temp=1; if(sta[i]%mod==0) continue; if(sta[i]%mod==1){ // "互质" != "(mod m)=1" temp=(pow[i]*B+1)%mod; ans=ans*temp%mod; continue; } LL d=1,ni=1,y=1; ex_gcd(sta[i]-1,mod,d,ni,y); ni=(ni%mod+mod)%mod; temp=power(sta[i],(pow[i]*B+1)); temp=(temp-1+mod)%mod; ans=ans*temp%mod*ni%mod; } printf("%lld\n",ans); } return 0; } /* ex_gcd(i,9901,d,x,y); // i=0 -> x=0 i=-1 -> x=1 */
3.wilson 定理