题意:求A^B的所有因子之和
很容易知道,先把分解得到,那么得到,那么
的所有因子和的表达式如下
第一种做法是分治求等比数列的和
用递归二分求等比数列1+pi+pi^2+pi^3+...+pi^n:
(1)若n为奇数,一共有偶数项,则:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2) * (1+p^(n/2+1))
= (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))
(2)若n为偶数,一共有奇数项,则:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2-1) * (1+p^(n/2+1)) + p^(n/2)
= (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);
其他用到的知识是素数筛选以及快速幂,本博客都有相应知识或者百度也行
#include<stdio.h> #include<string.h> typedef long long ll; const int mod=9901; const int N=1e5+11; int p[N],pr[N],cnt; void init(){ for(int i=2;i<N;i++){ if(!p[i]) pr[++cnt]=i; for(int j=1;j<=cnt&&i*pr[j]<N;j++){ p[i*pr[j]]=1; if(i%pr[j]==0) break; } } } ll pow_m(ll a,ll b,ll m){ ll ans=1;a%=m; while(b){ if(b&1) ans=(ans*a)%m; a=(a*a)%m; b>>=1; } return ans; } ll sum(ll p,ll n){ if(!n) return 1; if(n&1){ return (sum(p,n/2)*(1+pow_m(p,n/2+1,mod)))%mod; } else{ return (sum(p,n/2-1)*(1+pow_m(p,n/2+1,mod))+pow_m(p,n/2,mod))%mod; } } int main(){ ll a,b; init(); while(~scanf("%lld%lld",&a,&b)){ ll ans=1; for(int i=1;i<=cnt&&pr[i]*pr[i]<=a;i++){ if(a%pr[i]==0){ int num=0; while(a%pr[i]==0){ num++; a/=pr[i]; } ans=(ans*sum(pr[i],num*b))%mod; } } if(a>1){ ans=(ans*sum(a,b))%mod; } printf("%lld\n",ans); } return 0; }
第二种方法就是用等比数列求和公式,但是要用逆元。用如下公式即可(已知a|b)
我们来证明它,已知,证明步骤如下
在快速幂时的乘法会爆longlong,所以用快速乘
#include<stdio.h> #include<string.h> typedef long long ll; const int mod=9901; const int N=1e5+11; int p[N],pr[N],cnt; void init(){ for(int i=2;i<N;i++){ if(!p[i]) pr[++cnt]=i; for(int j=1;j<=cnt&&i*pr[j]<N;j++){ p[i*pr[j]]=1; if(i%pr[j]==0) break; } } } ll mul(ll a,ll b,ll m){ ll ans=0;a%=m; while(b){ if(b&1) ans=(ans+a)%m; a=(a+a)%m; b>>=1; } return ans; } ll pow_m(ll a,ll b,ll m){ ll ans=1;a%=m; while(b){ if(b&1) ans=mul(ans,a,m); a=mul(a,a,m); b>>=1; } return ans; } int main(){ ll a,b; init(); while(~scanf("%lld%lld",&a,&b)){ ll ans=1; for(int i=1;i<=cnt&&pr[i]*pr[i]<=a;i++){ if(a%pr[i]==0){ int num=0; while(a%pr[i]==0){ num++; a/=pr[i]; } ll M=(pr[i]-1)*mod; ans*=(pow_m(pr[i],num*b+1,M)+M-1)/(pr[i]-1); ans%=mod; } } if(a>1){ ll M=(a-1)*mod; ans*=(pow_m(a,b+1,M)+M-1)/(a-1); ans%=mod; } printf("%lld\n",ans); } return 0; }
http://blog.csdn.net/lyy289065406/article/details/6648539
http://blog.csdn.net/acdreamers/article/details/8220787
时间: 2024-11-16 23:06:20