POJ1845 Sumdiv

题目大意:就是求S(A^B)%9901,S函数表示A^B的因子和。其实一开始我想到杭电的1452的happy 2004.就是用逆元的做法,后来跪了~~因为P-1不一定和9901互质啊~~所以求逆元的定理要求不满足,所以在这种情况下不能用逆元的做法来做。

只能用等比数列的二分法来做。

首先是求出A的素因子:P1^k1 *  P2^k2   *   P3^k3  *  P4^k4  *……  *   Pn^kN;

所以A^B就是:P1^(k1*B) *  P2^(k2*B)   *   P3^(k3*B)  *  P4^(k4*B)  *……  *   Pn^(kN*B);

所以由初等数论定理知道:因子和为:(P1^0+P1^1+P1^2+……+P1^(k1*B)  )*  (P2^0+P2^1+P2^2+……+P2^(k2*B)  ) *……*(PN^0+PN^1+PN^2+……+PN^(kN*B)  )

(直接用等比数列求和会有逆元,所以不能用)

下面以怎么样求::P1^0+P1^1+P1^2+……+P1^(k1*B) (一) 作为例子讲说:

令n=k1*B

当n为奇数的时候:

原式等于:P1^0+P1^1+……+P1^(n/2)*(P1^(n/2+1)  +1)

当n为偶数数的时候:

原式等于:P1^0+P1^1+……+P1^(n/2-1)*(P1^(n/2+1)  +1)+P1^(n/2)

这2道式子都满足递推式,所以可以2分递归解决

 


AC program:

#include<iostream> 
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int pp[100005];
int nn[100005];
__int64 ppw(__int64 p,__int64 k)
{
  if(k==1)return p%9901;
  __int64 tmp=ppw(p,k/2);
  __int64 tmppp=tmp*tmp%9901;
  if(k&1)return tmppp*p%9901;
  return tmppp;       
}
__int64 fen(__int64 p,__int64 k)
{                                                      //其实因为在分的时候要判断奇偶,所以就放进里面
  if(k==0)return 1;
  if(k&1)return fen(p,k/2)*(ppw(p,k/2+1)+1)%9901;                            
  return (fen(p,k/2-1)*(ppw(p,k/2+1)+1)%9901+ppw(p,k/2)%9901)%9901 ;
     

}
int main()
{
__int64 n,k; //讨厌想哪个变量要LL,所以全场LL
while(cin>>n>>k)
{
  __int64 tmp=n;//因为循环里面要用到n,n又要变小,有时真是挫~~这个错误一错的话,估计又要调试好久~~
  __int64 kg=0;
  for(__int64 i=2;i*i<=tmp;)//简单高效的素数提取方法,细细品味
   {
      if(n%i==0)
        {
          pp[kg]=i;
          __int64 cnt=0;
          while(n%i==0)
            {
              n/=i;     
              cnt++;      
            }       
          nn[kg++]=cnt; 
        }            
      else i++;
   }
   if(n!=1)
      {
        pp[kg]=n;
        nn[kg++]=1;     //素数个数的映射数组
      }   
   __int64 sum=1;
   for(__int64 i=0;i<kg;i++)//对每个素数因子的等比数列求和2分
     {
        sum= (    sum*fen(pp[i],nn[i]*k)   )%9901;        
     } 
   cout<<sum<<endl;                 
}
return 0;}


 

 

 小优的博客说的很详细很基础:http://www.cnblogs.com/lyy289065406/archive/2011/07/31/2122790.html

再转一篇用逆元做的:http://www.2cto.com/kf/201208/149564.html

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值