poj1845 数论好题

求a^b的所有因数和。(a,b<=50000000)

分解质因数 a=a1^b1*a2^b2*...*an^bn

则 因数和为(a1^0+a1^1+...+a1^b1)*(a2^0+a2^1+...+a2^b2)*...(an^0+an^1+...+an^bn) (乘法原理)

a^b=a1^(b1*b)*a2^(b2*b)*...*an^(bn*b) 

因数和为(a1^0+a1^1+...+a1^(b1*n))*(a2^0+a2^1+...+a2^(b2*n))*...(an^0+an^1+...+an^(bn*n))

等比数列求和。。a1*(1-q^n)/(1-q)

逆元inv(0)不存在。。坑死。。所以inv(Mo),inv(2*Mo)...都不存在。。

而q-1=k*Mo时,这一项就相当于b2*x+1个1相加。。然后就好办了。。

对逆元的理解还是欠缺的。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define N 100000
#define Mo 9901
using namespace std;
int a,b,t,cnt;
long long ans=1;
int p[N],prime[N],counter[N];
long long pow(int a,int b,int p){
	long long ret=1,base=a;
	while(b){
		if(b&1) ret=(ret*base)%p;
		base=(base*base)%p;
		b=b>>1;
	}
	return ret;
}
int main(){
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	scanf("%d%d",&a,&b);
	if(a==0) {printf("0\n");return 0;}
	int t=(int)sqrt((double)a);
	fill(p,p+N,1);p[0]=p[1]=0;cnt=0;
	for(int i=2;i<=t;i++)
		if(p[i]) {
			for(int j=i*i;j<=t;j+=i) p[j]=0;
			prime[++cnt]=i;
		}
	int aa=a;
	for(int i=1;i<=cnt;i++)
		while(aa%prime[i]==0) aa/=prime[i],counter[i]++;
	if(aa!=1&&aa!=0) prime[++cnt]=aa,counter[cnt]=1;
	for(int i=1;i<=cnt;i++){
		if((prime[i]-1)%Mo==0) {ans=(ans*(counter[i]*b+1))%Mo;continue;}
		long long tmp=(pow(prime[i],counter[i]*b+1,Mo)+Mo-1)%Mo;
		ans=(ans*tmp)%Mo;
		ans=(ans*pow((prime[i]-1)%Mo,Mo-2,Mo))%Mo;
	}
	printf("%lld\n",ans);
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值