POJ1845(A^B的约数之和)

对 A进行质因子分解
A = P 1 k 1 P 2 k 2 P n k n A=P_1^{k_1}\cdot P_2^{k_2} \cdots \cdot P_n^{k_n}
所以
A B = ( P 1 k 1 P 2 k 2 P n k n ) B = P 1 k 1 B P 2 k 2 B P n k n B A^B=(P_1^{k_1}\cdot P_2^{k_2} \cdots \cdot P_n^{k_n})^B=P_1^{k_1B}\cdot P_2^{k_2B} \cdots \cdot P_n^{k_nB}
所以约数之和为
a n s w e r = ( 1 + P 1 + P 1 2 + + P 1 k 1 ) ( 1 + P 2 + P 2 2 + + P 2 k 2 ) ( 1 + P n + P n 2 + + P n k n ) answer=(1+P_1+P_1^2+\cdots+P_1^{k_1})\cdot(1+P_2+P_2^2+\cdots +P_2^{k_2})\cdot (1+P_n+P_n^2+\cdots+P_n^{k_n})
容易想到等比数列的前n项和公式,但这个公式里有要除以 P k 1 P_k-1
那么容易想到用逆元,但质数9901太小了,无法保证互质
所以只能换种办法求等比数列的前 n n 项和;
问题化为怎么求 p p 的前 n n 项和:
当n为奇数时
1 + p + p 2 + p 3 + . . . + p 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^{n/2+1}+ p\cdot(1+p^{n/2+1}) +\cdots+ p^{n/2} \cdot(1+p^{n/2+1})
= ( 1 + p + p 2 + . . . + p n / 2 ) ( 1 + p n / 2 + 1 ) = (1 + p + p^2 +...+ p^{n/2})\cdot(1 + p^{n/2+1})
当n为偶数时
1 + p + p 2 + p 3 + . . . + p 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 ) = (1+p^{n/2+1}+ p\cdot(1+p^{n/2+1}) +\cdots+ p^{n/2-1} \cdot(1+p^{n/2+1})
= ( 1 + p + p 2 + . . . + p n / 2 1 ) ( 1 + p n / 2 + 1 ) + p n / 2 = (1 + p + p^2 +...+ p^{n/2-1})\cdot(1 + p^{n/2+1})+p^{n/2}
所以递归求即可
代码:

#include<iostream>
#include<cstring>
#define ll long long
#define endl '\n'
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
const int MX=4e2+7;
const int mod=9901;
using namespace std;
int p[MX],k[MX];
ll qpow(ll a,ll b,ll MOD=mod){for(ll ans=1;;a=a*a%MOD,b>>=1){if(b&1)ans=ans*a%MOD;if(!b)return ans;}}
ll inv(ll a,ll MOD=mod){return qpow(a,MOD-2,MOD);}
ll __gcm(ll a,ll b){return a*b/__gcd(a,b);}
ll __get(ll a,ll b)
{
   ll ans=1;
   if(b==0)return 1;
   if(b==1)return a+1;
   if(b&1)
       ans=ans*__get(a,b/2)%mod*(1+qpow(a,b/2+1));
   else {
       ans=ans*__get(a,b/2-1)*(1+qpow(a,b/2+1))%mod+qpow(a,b/2);
       ans%=mod;
   }
   return ans;
}
int main()
{
 ios::sync_with_stdio(0),cin.tie(0);
 ll a,b;
 while(cin>>a>>b){
 memset(k,0,sizeof k);
 int top=0;
 for(int i=2;i*i<=a;i++)
 {
     if(a%i==0)
     {
         p[++top]=i;
         while(a%i==0)
         {
             a/=i;
             k[top]++;
         }
     }
 }
 if(a>1){
   p[++top]=a;
   k[top]=1;
 }
 ll ans=1;
 rep(i,1,top) ans=ans*__get(p[i],b*k[i])%mod;
 cout<<ans<<endl;
 }
}

发布了109 篇原创文章 · 获赞 35 · 访问量 6009

猜你喜欢

转载自blog.csdn.net/weixin_43965698/article/details/104163287