题目大意:就是求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