首页 > 代码库 > CODEVS1172 Hankson的趣味题(。。。)
CODEVS1172 Hankson的趣味题(。。。)
Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫Hankson。现
在,刚刚放学回家的Hankson 正在思考一个有趣的问题。
今天在课堂上,老师讲解了如何求两个正整数c1 和c2 的最大公约数和最小公倍数。现
在Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公
倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整
数x 满足:
1. x 和a0 的最大公约数是a1;
2. x 和b0 的最小公倍数是b1。
Hankson 的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的
x 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x 的个数。请你帮
助他编程求解这个问题。
输入描述 Input Description
第一行为一个正整数n,表示有n 组输入数据。接下来的n 行每
行一组输入数据,为四个正整数a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入
数据保证a0 能被a1 整除,b1 能被b0 整除。
输出描述 Output Description
每组输入数据的输出结果占一行,为一个整数。
对于每组数据:若不存在这样的 x,请输出0;
若存在这样的 x,请输出满足条件的x 的个数;
思路:分解质因数,然后就是美丽的乘法原理了,思路不是很难,但是有了思路之后苦苦看了。。。近两个小时,疯了。。。先对最小公倍数分解质因数,将质因数和个数存于结构体中,然后对其他的三个数进行分解,将质因数和最小公倍数的结构体下标相对应(方便后面计算)。根据唯一分解定理,可以将一个数分解成多个素数乘积的形式,而两个数的最大公约数就是两个数同底数较小指数的幂的乘积;最小公倍数就是两个数同底数较大指数的幂的乘积。然后对每一个底数的指数的范围进行求解,分为以下几种情况:
1)b1<a1,直接输出0;
2)a1<a0&&b1>b0&&b1>a1, 直接输出0;
3)a1<a0,则指数只能取a1,continue;
4)b1>b0,则指数只能取b1,continue;
5)一般情况:范围是(a1~b1)。
ans=(max-min)*(max-min)*……。
一开始用的数组下标代表质因数,数组中的是个数,然后美丽的RC、TLE了,后来借鉴了网上的解析,改成了结构体,并发现了最小公倍数的质因数一定是四个数中最全的这个美丽fact。还有就是质因数的分解,i从2——int(sqrt(b1))每次都将i除尽,然后能整除的就一定是质数了。。。
code:(用了二维数组代替美丽的结构体。。。比较肮脏啊!!!)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int ai0[10000][2]={0},ai1[10000][2]={0},bi0[10000][2]={0},
bi1[10000][2]={0},minn[10000]={0},maxn[10000]={0};
int main()
{
int n,a0,a1,b0,b1,ci,i,j,tt;
long long ans;
cin>>n;
for (ci=1;ci<=n;++ci)
{
cin>>a0>>a1>>b0>>b1;
memset(bi1,0,sizeof(bi1));
for (i=2;i<=int(sqrt(b1));++i)
{
if (b1%i==0)
{
++bi1[0][0];
bi1[bi1[0][0]][0]=i;
}
while (b1%i==0)
{
++bi1[bi1[0][0]][1];
b1=b1/i;
}
}
if (b1!=1)
{
++bi1[0][0];
bi1[bi1[0][0]][0]=b1;
bi1[bi1[0][0]][1]=1;
}
memset(ai1,0,sizeof(ai1));
for (i=1;i<=bi1[0][0];++i)
{
tt=0;
while (a1%bi1[i][0]==0)
{
++tt;
a1=a1/bi1[i][0];
}
++ai1[0][0];
ai1[ai1[0][0]][0]=bi1[i][0];
ai1[ai1[0][0]][1]=tt;
}
memset(bi0,0,sizeof(bi0));
for (i=1;i<=bi1[0][0];++i)
{
tt=0;
while (b0%bi1[i][0]==0)
{
++tt;
b0=b0/bi1[i][0];
}
++bi0[0][0];
bi0[bi0[0][0]][0]=bi0[0][0];
bi0[bi0[0][0]][1]=tt;
}
memset(ai0,0,sizeof(ai0));
for (i=1;i<=bi1[0][0];++i)
{
tt=0;
while (a0%bi1[i][0]==0)
{
++tt;
a0=a0/bi1[i][0];
}
++ai0[0][0];
ai0[ai0[0][0]][0]=ai0[0][0];
ai0[ai0[0][0]][1]=tt;
}
ans=1;
for (i=1;i<=bi1[0][0];++i)
{
if (bi1[i][1]<ai1[i][1])
{ ans=0;break;}
if(ai1[i][1]<ai0[i][1]&&bi1[i][1]>bi0[i][1]&&bi1[i][1]>ai1[i][1]) {ans=0;break;}
if(ai1[i][1]<ai0[i][1]) {minn[i]=ai1[i][1];maxn[i]=ai1[i][1];continue;}
if(bi1[i][1]>bi0[i][1]) {minn[i]=bi1[i][1];maxn[i]=bi1[i][1];continue;}
minn[i]=ai1[i][1];
maxn[i]=bi1[i][1];
}
if (ans==1)
for (i=1;i<=bi1[0][0];++i)
ans=ans*(maxn[i]-minn[i]+1);
cout<<ans<<endl;
}
}
CODEVS1172 Hankson的趣味题(。。。)