poj 1845 Sumdiv(数论+二分)
刚开始学习数论,不知道该从哪方面学起,就找了这道题做做,希望通过做题能找到学习数论的方向。花了有两天的时间终于弄懂了这题的思想,恩,数论真的很神奇!
题意是:求a^b的所有因子的和取余9901后的结果。
用到的知识点有:
(1)素因子分解唯一性定理:任意正整数都能用一种方式且只有一种方式写出素数的乘积。如: 60 =2^2*3*5
(2)约数和公式: 将A^B 分解成素因数形式:A^B=(p1^k1)*(p2^k2)*(p3^k3)………
那么A^B所有因子之和就是 S=(1+p1+p1^2+p1^3+…..p1^k1)*(1+p2+p2^2+p2^3+…..p2^k2)*(1+p3+…)*…………..
然后就是二分法求a^b和所有因子的和了。
我觉得下面的博客写的很好,比较容易理解,可以参考一下。
http://hi.baidu.com/aconly/blog/item/1a25845d1bfbbc44fbf2c0bf.html
还有一点,就是按位与可以用来判断k的奇偶性~~
代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define maxx 7100 #define mod 9901 __int64 p[maxx],f[maxx],s; void init()//筛选法求素数 { int i,j; memset(f,0,sizeof(f)); s=0; for(i=2;i<maxx;i++) { if(!f[i]) { p[s++]=i; for(j=2*i;j<maxx;j+=i) f[j]=1; } } } __int64 exp(__int64 a,__int64 b)//二分计算a^b; { if(1==b) return a; __int64 k = exp(a,b/2); if(b&1)//判断奇偶 return (k*k*a)%mod; else return (k*k)%mod; } __int64 sum(__int64 a,__int64 b) { if(b==1) return 1; __int64 k; k = sum(a,b/2); if(b&1) return (k+exp(a,b/2)*(1+a*k))%mod;//k为奇数时。 else return ((1+exp(a,b/2))*k)%mod;//k为偶数时。 } int main() { int a,b; int i,j; init(); while (scanf("%d%d",&a,&b)!=EOF) { __int64 cnt = 1; for(i=0;i<s&&a>1;i++) { int k=0; while(a%p[i]==0) { k++; a=a/p[i]; } if(k) cnt = (cnt*sum(p[i],k*b+1))%mod; } if (a > 1)//a为素数 cnt = (cnt*sum(a,b+1))%mod; printf("%I64d\n",cnt); } return 0; }