POJ1845 数学

题意:求A^B的所有约数之和 Mod 9901。

思路:大数模运算。两个最基本公式:(A*B)%C = ((A%C)*(B%C))%C 和 (A+B)%C = ((A%C)+(B%C))%C 。用__int64的原因为 n = cnt[i] * B (cnt[i]为A第i个素因子的个数)可能会超int。

 

1: 对A进行素因子分解得

     A = p1^a1 * p2^a2 * p3^a3 *...* pn^an.
  故 A^B = p1^(a1*B) * p2^(a2*B) *...* pn^(an*B);


2:A^B的所有约数之和为:

     sum = [1+p1+p1^2+...+p1^(a1*B)] * [1+p2+p2^2+...+p2^(a2*B)] *...* [1+pn+pn^2+...+pn^(an*B)].

  如 200 = 2^3 * 5^2 :  sum(200) = [1 + 2 + 4 + 8] * [1 + 5 + 25].


3: 求等比数列1+pi+pi^2+pi^3+...+pi^n可以由递归形式的二分求得:(模运算不能用等比数列和公式!)
   若n为奇数,一共有偶数项,则:
      1 + p + p^2 + p^3 +...+ p^n

      = (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2) * (1+p^(n/2+1))
      = (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))

   如:1 + p + p^2 + p^3 + p^4 + p^5 = (1 + p + p^2) * (1 + p^3)
   若n为偶数,一共有奇数项,则:
      1 + p + p^2 + p^3 +...+ p^n

      = (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2-1) * (1+p^(n/2+1)) + p^(n/2)
      = (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);

   如:1 + p + p^2 + p^3 + p^4 = (1 + p) * (1 + p^3) + p^2

 

 

 

 

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<vector>
#define tree int o,int l,int r
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lo o<<1
#define ro o<<1|1
#define Uint unsigned int
#define UI unsigned int
#define inf 0x7fffffff
#define eps 1e-7
#define N 109
#define M 9901
using namespace std;
int T,n,m,k,t;
int p[N];
int num[N];
int dfs(int ep,int k,int &d)
{
    if(k==1)
    {
        d=ep;
        return 1;
    }
    int dd;
    int he=dfs(ep,k>>1,dd);
    if(k%2==0)
    {
        he=(he+he*dd)%M;
        d=(dd*dd)%M;
        return he;
    }
    else
    {
        d=dd;
        dd=(dd*ep)%M;
        he=(he+he*dd+d)%M;
        d=(dd*d)%M;
        return he;
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    int cnt=0;
    int a,b;
    while (scanf("%d%d",&a,&b)==2)
    {
        memset(num,0,sizeof(num));
        int x=a;
        cnt=0;
        for(int i=2; i<=x&&x>1; i++)
            if(x%i==0)//x%i==0则i一定是质数
            {
                p[cnt]=i;
                while(x%i==0)
                {
                    num[cnt]++;
                    x/=i;
                }
                cnt++;
            }
        for (int i=0; i<cnt; ++i )
        {
            num[i]=(num[i]*b+1);
        }
        int ans=1;
        for (int i=0; i<cnt; ++i )
        {
            int te;
            int he=dfs(p[i]%M,num[i],te);
            ans=(ans*he)%M;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2013-06-22 23:54  baoff  阅读(147)  评论(0编辑  收藏  举报