CODEVS1172 Hankson的趣味题(。。。)

 题目描述  Description

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;

    }

你可能感兴趣的:(code)