poj1845

题目大意:给出A,B    求出A的B次幂的约数(因子)之和


思路: 这道题运用到数论的三大内容

           

           1>  任意一个整数都可以写成质数的N次幂的乘积

                        A=(p1^ k1)*(p2^k2)*(p3^k3)...........(pn^kn)

                       其中p1,p2,p3.....pn 为素数


           2>  某数A的质因子M之和 

                        M= (p1^0+p1^1+p1^2.......+p1^k1)*(p2^0+p2^1+p2^2.......+p2^k2)*........

                        


           3> 同余定理

                        (A+B) mod X= (AmodX + BmodX) modX;

                        (A*B)  mod X=  (AmodX * BmodX) modX;


应用到这道题中:

第一步:分解A

               首先对A进行素数的分解,从2开始,进行分解

                         如: 在A%2!=0  的情况下 记录A/2的次数以得到它的幂,并且

                                   不断进行A/=2

                如此,对之后的每个素数进行这样的运算,知道A=1

                但是,当A本身就是一个素数时,无法进行分解,此时把A存入。


第二步:计算每一个Sum=(p^0+p^1+p^2.........p^n)

                当n是奇数时 : Sum=(p^0+p^1.....p^n/2)(1+p^n/2);

                当n是偶数时 : Sum=(p^0+p^1.....p^n/2-1)(1+p^n/2+1)+p^n/2 ;

                          如此,就可以把求Sum的过程看成一个递归函数,不断递归,更加方便求出


第三步:计算p^n

                根据一下定理:

                q1=p*p;         则 n=n/2;

                q2=q1*q1;     则n=n/2;

                ........

                如此  2^8=256   只需要计算3次 

                        2*2=4   4*4 =16   16*16=256;


                sum=1 

               若n为奇数则可以先进行一次乘法,使得n变为偶数

               按照n为偶数的方式不断进行p=p*p  sum*=p   直到 n=0


代码如下:

#include <queue>
#include <stack>
#include <math.h>
#include <vector>
#include <limits.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <functional>
using namespace std;
#define size 10000
#define mod 9901

__int64 get(__int64 p,__int64 n)
{
     __int64 result=1;
     while(n>0)
     {
          if(n%2)
               result=(result*p)%mod;
          p=p*p%mod;
          n/=2;
     }
     return result;
}

__int64 every(__int64 p,__int64 n)
{
     if(n==0)
          return 1;
     if(n%2)
          return (every(p,n/2)*(1+get(p,n/2+1)))%mod;
     else
          return (every(p,n/2-1)*(1+get(p,n/2+1))+get(p,n/2))%mod;
}


int main()
{
    int p[size],n[size];
    int i;
    int A,B;
    int ans=1;
    while(cin >> A >> B)
    {
         int k=0;
         for(i=2; i*i<=A;)
         {
              if(!(A%i))
              {
                   p[k]=i;
                   n[k]=0;
                   while(!(A%i))
                   {
                        n[k]++;
                        A/=i;
                   }
                   k++;
              }
              if(i==2)
                  i++;
              else
                  i+=2;
         }
         if(A!=1)
         {
              p[k]=A;
              n[k++]=1;
         }

         for(i=0; i<k; i++)
              ans=(ans*(every(p[i],n[i]*B))%mod)%mod;

         cout << ans << endl;
    }
    return 0;
}


                                   

              

               



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值