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

 

 

posted @ 2012-05-03 17:07  Misty_1  阅读(308)  评论(3编辑  收藏  举报