poj1845
题目链接:Click here
Solution:
不妨先对A进行分解质因数,\(A=p_1^{c_1}\times p_2^{c_2} \times \dots \times p_n^{c_n}\)
那么\(A^B=p_1^{c_1\times B}\times p_2^{c_2\times B} \times \dots \times p_n^{c_n\times B}\),A的所有约数则可以表示为\(\{p_1^{d_1}\times\dots\times p_n^{d_n}|d_1\leq c1\times B,\dots\}\)
由组合数学的知识,我们可以知道\(\sum divs(A^B)=\prod_{i=1}^n(\sum_{j=0}^{c_i\times B}p_i^j)\)
注意到我们需要模意义下的答案,这让我们不由得想到费马小定理,然而对这道题来说,我们可以换一种方法
可以发现,我们现在主要的问题便是求模意义下的\(\sum_{j=0}^{c_i\times B}p_i^j\),这是一个等比数列,由于我们要mod 9901,所以不能直接用公式来求(因为等比数列的公式考虑除法),我们可以考虑使用分治的思想来求解
时间复杂度\(O(\sqrt A+\log A+\log B)\)
Code
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
const int mod=9901;
int n,m,tot,ans=1;
vector<int> divs,c;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
void work(int x){
for(int i=2;i*i<=x;i++){
if(x%i!=0) continue;
++tot;divs.push_back(i);
int num=0;
while(x%i==0){
++num;
x=x/i;
}
c.push_back(num);
}
if(x>1){
++tot;
divs.push_back(x);
c.push_back(1);
}
}
int qpow(int q,int v){
int re=1;
while(v){
if(v&1) re=re*q%mod;
q=q*q%mod;v>>=1;
}
return re;
}
int calc(int q,int len){
if(len==1) return 1;
int v1=(1+qpow(q,len>>1))%mod;
int v2=calc(q,len>>1)%mod;
if(len&1) return (v1*v2%mod+qpow(q,len-1))%mod;
return v1*v2%mod;
}
signed main(){
n=read(),m=read();
work(n);
for(int i=0;i<tot;i++)
ans=ans*calc(divs[i],c[i]*m+1)%mod;
cout<<ans<<endl;
return 0;
}