You are given two integers a and b. In one turn, you can do one of the following operations:
Take an integer c (c>1 and a should be divisible by c) and replace a with ac;
Take an integer c (c>1 and b should be divisible by c) and replace b with bc.
Your goal is to make a equal to b using exactly k turns.
For example, the numbers a=36 and b=48 can be made equal in 4 moves:
c=6, divide b by c ⇒ a=36, b=8;
c=2, divide a by c ⇒ a=18, b=8;
c=9, divide a by c ⇒ a=2, b=8;
c=4, divide b by c ⇒ a=2, b=2.
For the given numbers a and b, determine whether it is possible to make them equal using exactly k turns.
Input
The first line contains one integer t (1≤t≤104). Then t test cases follow.
Each test case is contains three integers a, b and k (1≤a,b,k≤109).
Output
For each test case output:
“Yes”, if it is possible to make the numbers a and b equal in exactly k turns;
“No” otherwise.
The strings “Yes” and “No” can be output in any case.
Example
inputCopy
8
36 48 2
36 48 3
36 48 4
2 8 1
2 8 2
1000000000 1000000000 1000000000
1 2 1
2 2 1
outputCopy
YES
YES
YES
YES
YES
NO
YES
NO
题目大意:就是求两个数a,b是否能在k次变换内使得两数相同。
题解:就是求两个数最多可有几个数相乘而得,但k=1时应特殊判断。
下面是超时代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
int count(int a)
{
int sum=0,i;
for(i=2;i<=sqrt(a);i++)
{
while(a%i==0)
{
sum++;
a/=i;
}
}//这几行代码就是求出两个数最多可有几个数相乘而得
if(a>1)
sum++;//这主要是
return sum;
}
int main()
{
int t,x,y,a,b,k;
cin>>t;
while(t--)
{
cin>>a>>b>>k;
if(k==1)
{
if(a!=b&&(__gcd(a,b)==a||__gcd(a,b)==b))
printf("YES\n");
else
printf("NO\n");
}
else
{
int x=count(a);
int y=count(b);
if(k>=2&&k<=x+y)
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}
下面是AC代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
int count(int a)
{
int sum=0,i;
for(i=2;i*i<=a;i++)
{
while(a%i==0)
{
sum++;
a/=i;
}
}
if(a>1)
sum++;//最后剩下的是质数,所以加上它本身作为一个因子。
return sum;
}
int main()
{
int t,x,y,a,b,k;
cin>>t;
while(t--)
{
cin>>a>>b>>k;
if(k==1)
{
if(a!=b&&(__gcd(a,b)==a||__gcd(a,b)==b))
printf("YES\n");
else
printf("NO\n");
}//k=1时的分类。
else
{
int x=count(a);
int y=count(b);
if(k>=2&&k<=x+y)
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}
对比可以看出,两个代码仅查了是ii<=a还是i<=sqrt(a),可以看出,ii<=a相比于后者更快一些。所以以后建议用前者。
下面是我做题时写的代码,但错了。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
bool sushu(int n)
{
int i;
if(i==1) return 0;
for(i=2;i<=sqrt(n);i++)
{
if(n%i==0)
return 0;//0表示不为素数。
}
return 1;
}
long long gcd(long long a,long long b)
{
if(a<=0 || b<=0) return 0; //如果传进来的参数小于0则返回0
else if(a%b==0) return b; //如果b能被a整除则b就是最大公约数
else
return gcd(b,a%b); //递归 调用函数本身
}
int main()
{
long long n,m,k,i,j;
long long t;
cin>>t;
while(t--)
{
long long sum2=2,min1,sum1=2;
cin>>n>>m>>k;
long long g=gcd(n,m);
if(g==n&&g!=m)
min1=1;
else if(g!=n&&g==m)
min1=1;
else
min1=2;
for(i=2;i<=sqrt(n);i++)
{
while(n%i==0)
{
sum1++;
n=n/i;
}
if(n<i)
break;
}
for(j=2;j<=sqrt(m);j++)
{
while(m%j==0)
{
sum2++;
m=m/j;
}
if(m<j)
break;
}
if(k<=sum1+sum2-2&&k>=min1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
可以看出这个代码写的很冗长,而且错误点很多。而且考虑的时候不是按k考虑的,而时生硬的一种一种情况的列举,很容易错,而且,没有用gcd函数,而是手写gcd,多此一举,这里我感觉应该是求两者最大的相乘时错了。所以这个题学到的还是挺多的。当然,此题未考虑k=0的情况,如果改变了k的范围,此题多加一个特判就行了。