POJ1845 数论

原题链接:http://poj.org/problem?id=1845

题目大意:求A^B的因子和

题解:

对于A^B=(\prod_{k=0}^m p_{k}^{tk} )^B=\prod_{k=0}^mp_k^{tk*B}所有的因子和则有:

(p_0^0+p_0^1+p_0^2+...+p_0^{t0*B})*(p_1^0+p_1^1+p_1^2+...+p_1^{t1B})...=\prod _{k=0}^m\sum _{i=0}^{t_k*B}p_k^i

观察\prod _{k=0}^m\sum _{i=0}^{t_k*B}p_k^i,显然是等差数列求和所以:\prod _{k=0}^m (p_k^{t_k*B+1}-1)/(p_k-1)

由于除法求模可以用费马小定理求逆元:

\prod _{k=0}^m (p_k^{t_k*B+1}-1)*(p_k-1)^{M-2}(mod M)

要注意当(pk-1+M)%M==0时要单独处理相当于 pk==1 

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
typedef long long ll;
using namespace std;
const int N=55000;
const int M=9901;
ll prime[N],c[N];
ll a,b,cnt,ans;
inline void pre(ll a){
	cnt=0;//预处理因子 
	for(register ll i=2;i*i<=a;i++){
		if(a%i==0){
			prime[++cnt]=i;c[cnt]=0;
			while(a%i==0){	c[cnt]++; a/=i; }
		}
	}	
	if(a>1) prime[++cnt]=a,c[cnt]=1;
} 
inline ll pow_mod(ll a,ll b){ 
	ll ans=1;
	while(b){
		if(b&1) ans=ans*a%M; 
		b>>=1;a=a*a%M; 
	} 
	return ans%M;
}
int main(){
//	freopen("poj1845.in","r",stdin);
	scanf("%lld%lld",&a,&b);
	pre(a);ans=1ll;
	for(int i=1;i<=cnt;i++){
		//逆元不存在 
		if((prime[i]-1)%M==0){
			ans=ans*(c[i]*b+1)%M;
			continue;
		}
		ll y=(prime[i]-1+M)%M;
		ll x=pow_mod(prime[i],c[i]*b+1);
		x=(x-1+M)%M; y=pow_mod(y,M-2);
		ans=ans*x%M*y%M;
	}
	printf("%lld\n",ans);
	return 0;
}

 

 

posted @ 2018-11-24 19:39  Exception2017  阅读(88)  评论(0编辑  收藏  举报