https://zhixincode.com/contest/3/problem/C?problem_id=36
题意:将两个数
分别拆成
个数
和
,且每对
与
互质,若有多组符合条件,输出
最小的任意一组。
即
且对于任意
,
。
这题wls说卡构造,暴力找素数试就可以过,然而被我们用十分妖娆的方式构造给过了。。。
首先如果想到了两个数都是偶数的情况,假设两个数中的较小值为
,较大值为
,可以将
拆成
和
,把
拆成
和
,因为
和
都是偶数,所以
必定是个奇数,该奇数必定与
互质,而相邻的两个数
与
也必定是互质的。同理,对于两个奇数的情况这样构造也是可以的。但是在测试时发现,如果两个数相等,
不符合题目要求,因此需要特判这种情况,随便用两个素数就可以构造出该情况的解。
然后考虑两个数一奇一偶的情况,假设两个数中的奇数为
,偶数为
,可以将A拆成
和
,将
拆成
和
,这样
是奇数,显然
和
可以保证互质,但是
与
可能不互质,所以需要判断
是否是
的倍数。如果是
的倍数,则将
拆成
和
,否则拆成
和
,这样因为如果
是
的倍数,
必定不是
的倍数。但是此时又有一个小问题就是当
时,
又不符合题目要求,因此有需要特判这种情况,可以将
拆成
和
,将
拆成
和
。
就这样,在又臭又多的特判下,冗长丑陋的代码就可以过了这个题,而且覆盖所有可能情况。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int T;
long long a,b;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&a,&b);
if(__gcd(a,b)==1)
printf("1\n%lld %lld\n",a,b);
else
{
if(a==b)
{
printf("2\n");
printf("%lld %lld\n",2LL,3LL);
printf("%lld %lld\n",a-2LL,b-3LL);
}
else if((a%2==0&&b%2==0)||(a%2==1&&b%2==1))
{
if(a<b)
{
printf("2\n");
printf("%lld %lld\n",2LL,b-(a-1LL));
printf("%lld %lld\n",a-2LL,a-1LL);
}
else
{
printf("2\n");
printf("%lld %lld\n",a-(b-1LL),2LL);
printf("%lld %lld\n",b-1LL,b-2LL);
}
}
else
{
if(a%2==1)
{
if((a-2)%3==0)
{
if(a==5)
{
printf("2\n");
printf("%lld %lld\n",2LL,b-5LL);
printf("%lld %lld\n",3LL,5LL);
}
else
{
printf("2\n");
printf("%lld %lld\n",4LL,b-3LL);
printf("%lld %lld\n",a-4LL,3LL);
}
}
else
{
printf("2\n");
printf("%lld %lld\n",2LL,b-3LL);
printf("%lld %lld\n",a-2LL,3LL);
}
}
else
{
if((b-2)%3==0)
{
if(b==5)
{
printf("2\n");
printf("%lld %lld\n",a-5LL,2LL);
printf("%lld %lld\n",5LL,3LL);
}
else
{
printf("2\n");
printf("%lld %lld\n",3LL,b-4LL);
printf("%lld %lld\n",a-3LL,4LL);
}
}
else
{
printf("2\n");
printf("%lld %lld\n",3LL,b-2LL);
printf("%lld %lld\n",a-3LL,2LL);
}
}
}
}
}
return 0;
}