【算法競賽進階指南】POJ1845Sumdiv
阿新 • • 發佈:2018-12-03
分解質因數 algo i++ cin std ++ sin namespace mpfr 如果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})\)
本題目是一道數論的綜合題目,主要的一個點就是利用二分法來求等比數列的和,其余的點就是唯一分解定理分解質因數,還有就是快速冪
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