您的位置:首页 > 其它

UVa 10892 LCM Cardinality (分解质因数+数学)

2015-02-04 15:04 295 查看
本题挺经典的,sqrt(n)时间复杂度分解质因数。

先看一个公式,数字a=p1^a1*p2^a2*p3^a3.........,b=p1^b1*p2^b2*p3^b3(其中pi为质因数,ai,bi为幂次),那么他们的LCM c=p1^max(a1,b1)*p2^max(a2,b2)..........,同理gcd是取每个质因数幂次最小值。

这样,如果lcm:c确定了,且c=p1^c1*p2^c2*p3^c3.........,那么得到他的两个数a,b中,对于每个pi,a,b中一个数的pi的幂次等于c1,另一个小于等于c1,这样对于每个pi,a的幂次为ci时b可以是0~ci-1,b为ci时a同理,再加上a,b同为ci的情况,对于每个pi方案数就是2*c1+1,把这些数乘法原理乘起来,除了(c,c)这组数,每个数都出现了2次,所以最后结果除2加1。

剩下的问题就是如何对10^9大小的数分解质因数。

遍历到根号n,对每个能整除n的数都一直除,这样根号n一下的质因子肯定都处理完了。可以证明,大于根号n的质因子至多有一个,且它的幂次为1。

证明:设p1,p2是n的质因子,且都大于根号n,那么n>=p1*p2,所有p1,p2不可能都大于根号n。

这样遍历到根号n后,只要判断下除剩下的n是不是等于1,大于一就说明还有一个大质数,再把结果乘3。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#include <algorithm>
#define LL long long

int N;
int main(){

	while(~scanf("%d",&N)){
		int k=N;
		LL res=1;
		if(!N) break;
		for(int i=2;i*i<=N;i+=2){
			int tmp=1;
			while(N%i==0){
				tmp++;
				N/=i;
			}
			res*=(2*tmp-1);
			if(i==2) i--;
		}
		if(N>1) res*=3;
		res/=2;
		res+=1;
		printf("%d %lld\n",k,res);
	}
	return 0;
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: