您的位置:首页 > 其它

LightOJ1236->算术基本定理

2016-07-13 00:58 302 查看
算术基本定理的应用

题意:找出对于整数对(i,j),他们的lcm为n,这样的整数对有多少。

思路:比如24=2^3*3^1:

(1)如果一个数完整地包含了3^1但是没有完整地包含2^3(一个数x完整地包含某个质因数p及其出现的次数t,指x可以被p^t整除),比如3,6,12,那么另一个数必须完整地包含2^3,比如8,24。那么此时有六种组合(3,8),(3,24),(6,8),(6,24),(12,8),(12,24)

(2)若一个数完整地包含2^3但是没有完整地包含3^1,比如8,那么另一个数必须完整地包含3^1,比如3,6,12,24,此时有4个。

(3)若一个数完整地包含了2^3和3^1,比如24,那么另一个数有(3+1)*(1+1)种可能,即1,2,3,4,6,8,12,24。

(4)若一个数既没有完整的包含2^3也没有完整地包含3^1,比如1,2,4,那么另一个数必须为24,此时有3种。

到此为止,你发现除了(24,24)这种组合只在(3)中出现一次,其他情况均出现2次。若上面的总数为t,那么答案为(t+1)/2。

假设lcm(X,Y)=M,分别分解X,Y,M

X=x1^a1*x2^a2...

Y=x1^b1*x2^b2..

M=x1^c1*x2^c2..

因为是公倍数 所以质因数肯定要相同

那么max(a1,b1)=c1...max(a2,b2)=c2。

当b1=c1的时候a1的取法是(c1+1)种,a1=c1是b1取法也是(c1+1)种,但是有两个(c1,c1),所有对于每一个c1来说总的取法是(2*c1+1).

因为要求i<=j,所以最后结果去重一下,但是(n,n)只有一次,那么解就是(ans+1)/2。

#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std ;
#define MAX 10000100
bool visit[MAX] ;
long long prime[MAX / 10] ;
int tot = 0 ;

void doprime()//素数筛
{
for(long long i = 2 ; i < MAX ; i ++)
{
if(! visit[i])
{
prime[tot ++] = i ;
for(long long j = i * i ; j < MAX ; j += i) visit[j] = true ;
}
}
}
int p[1000] ;//素因子
int a[1000] ;//素因子个数
int cnt ;
void sbreak(long long n)//素因子分解
{
memset(p , 0 , sizeof(p)) ;
memset(a , 0 , sizeof(a)) ;
cnt = 0 ;
for(int i = 0 ;prime[i] * prime[i] <= n ; i ++)
{
if(n % prime[i] == 0)
{
p[cnt] = prime[i] ;
while(n % prime[i] == 0)
{
a[cnt] ++ ;
n /= prime[i] ;
}
cnt ++ ;
}
}
if(n != 1)
{
p[cnt] = n ;
a[cnt ++ ] = 1 ;
}
}
int main()
{
int T ;
long long num ;
doprime() ;
cin >> T ;
for(int cas = 1 ; cas <= T ; cas ++)
{
cin >> num ;
sbreak(num) ;
long long ans = 1 ;
for(int i = 0 ; i < cnt ; i ++)
ans = ans * (a[i] * 2 + 1) ;
ans = (ans + 1) / 2 ;
printf("Case %d: %lld\n",cas,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: