POJ-1845 - Sumdiv (数学、定理 - 求A^B因子和)

问题题意:

给出两个数A、B (0<=A,B<=50000000),求出A^B的所有因子的和。

相关知识:

1、逆元

2、整数唯一分解定理

对于任意正整数都有且只有一种方式写出其素因子的乘积表达式,即:

A = (p1^k1) * (p2^k2) * (p3^k3) * ... ... * (pn^kn)     其中 pi 均为素数。

3、约束和公式

对于已经分解的整数 A = (p1^k1) * (p2^k2) * (p3^k3) * ... ... * (pn^kn) 

A 的所有因子之和为:

Sum = ( p1^0 + p1^1 + ... + p1^k1)*(p2^0 + p2^1 + ... + p2^k2)* ... *(pn^0 + pn^1 + ... + pn^kn)

解题步骤:

1、对A进行素因子分解

对2不断取模…直到a%2 != 0 时结束,继续对3取模,直到a%3 != 0 时结束……

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

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

2、根据分解出的式子进行求和(方法多种) 

代码(参考数学一本通):

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<iterator>
#include<set>
using namespace std;
typedef long long Lint;
typedef unsigned long long ULint;
const double pi=atan(1.)*4.;
const int max_n=1e5+1000;
const Lint mod=9901;
Lint p[100010];
Lint k[100010];
Lint prime[100010];
Lint cnt;
bool flag[100010];

void Init(){
	flag[1]=true;
	cnt=0;
	for(Lint i=2;i<100000;i++){
		if(flag[i]) continue;
		else prime[cnt++]=i;
		for(Lint j=2*i;j<100000;j+=i){
			flag[j]=true;
		}
	}
}
Lint poww(Lint a,Lint b){
	Lint res=1,base=a%mod;
	while(b){
		if(b&1)
			res*=base;
		res%=mod;
		base*=base;
		base%=mod;
		b>>=1;
	}
	return res%mod;
}
Lint fun(Lint pp,Lint nn){
	if(nn==0) return 1;
	if(nn%2==1)
		return (fun(pp,nn/2)*(1+poww(pp,nn/2+1)))%mod;
	else
		return (fun(pp,nn/2-1)*(1+poww(pp,nn/2+1))+poww(pp,nn/2))%mod;
}

void solve(Lint a,Lint b){
	if(a==0&&b!=0)
	{cout<<0<<endl;return;}
	Lint n=0;
	for(Lint i=0;i<cnt&&prime[i]*prime[i]<=a;i++){
		Lint f=0;
		while(a%prime[i]==0){
			f=1;
			p[n]=prime[i];
			k[n]++;
			a/=prime[i];
		}
		if(f) n++;
		if(a==1) break;
	}
	if(a!=1){
		p[n]=a;
		k[n++]=1;
	}
	for(Lint i=0;i<n;i++){
		k[i]*=b;
	}
	Lint res=1;
	for(Lint i=0;i<n;i++){
		res=(res*(fun(p[i],k[i])%mod))%mod;
	}
	cout<<res<<endl;
}
int main(){
	Init();
	Lint a,b;
	cin>>a>>b;
	solve(a,b);
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值