1. 程式人生 > >【算法競賽進階指南】POJ1845Sumdiv

【算法競賽進階指南】POJ1845Sumdiv

分解質因數 algo i++ cin std ++ sin namespace mpfr

本題目是一道數論的綜合題目,主要的一個點就是利用二分法來求等比數列的和,其余的點就是唯一分解定理分解質因數,還有就是快速冪

A^B約數和\(=(1+p_{1}+p_{1}^{2}+\cdot\cdot\cdot+p_{1}^{c1})*(1+p_{2}+p_{2}^{2}+\cdot\cdot\cdot+p_{2}^{c2})*\cdot\cdot\cdot*(1+p_{n}+p_{n}^{2}+\cdot\cdot\cdot+p_{n}^{cn})\)

如果c是奇數(一共有偶數項)\(sum(p,c)=(1+p+p^{2}+p^{3}+\cdot\cdot\cdot+p^{\frac{c-1}{2}})+(p^{\frac{c+1}{2}}+\cdot\cdot\cdot+p^{c})\\ =(1+p+p^{2}+p^{3}+\cdot\cdot\cdot+p^{\frac{c-1}{2}})+p^{\frac{c+1}{2}}(1+p+p^{2}+p^{3}+\cdot\cdot\cdot+p^{\frac{c-1}{2}}) \\=(1+p^{\frac{c+1}{2}})(1+p+p^{2}+p^{3}+\cdot\cdot\cdot+p^{\frac{c-1}{2}})\\=(1+p^{\frac{c+1}{2}})sum(p,\frac{c-1}{2})\)

如果c是偶數(一共有奇數項目)我們把最後一項單獨提出來,然後跟偶數項一樣處理\(sum(p,c)=sum(p,c-1)+p^{c}\)

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=9901;
int p[10010],c[10010];
int m;

ll quick_pow(ll a,ll b){//快速冪
    ll ans=1,base=a;
    while(b){
        if(b&1) ans=(ans*base)%mod;
        base=(base*base)%mod;
        b>>=1;
    }
    return ans;
}

void divide(int n){//分解質因數
    m=0;
    for(int i=2;i<=sqrt(n);i++){
        if(n%i==0){
            p[++m]=i,c[m]=0;
            while(n%i==0) n/=i,c[m]++;
        }
    }
    if(n>1)
        p[++m]=n,c[m]=1;
}

ll sum(ll dp,ll dc){
    //二分法求等比數列和
    if(dp==0) return 0;
    if(dc==0) return 1;
    if(dc&1){//c奇數
        return ((1+quick_pow(dp,dc/2+1))%mod*sum(dp,dc/2)%mod)%mod;
    }else{//c偶數
        return ((1+quick_pow(dp,dc/2))%mod*sum(dp,dc/2-1)+quick_pow(dp,dc))%mod;
    }
}

int main(){
    int a,b;
    while(cin>>a>>b){
    divide(a);//將底數分解
    int ans=1;
    for(int i=1;i<=m;i++){
        ans=(ans*sum(p[i],c[i]*b)%mod)%mod;
    }
    cout<<ans<<"\n";
    }
    return 0;
}

【算法競賽進階指南】POJ1845Sumdiv