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;
}

posted @ 2022-08-12 12:14  DQY_dqy  阅读(20)  评论(0编辑  收藏  举报