“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 19 天,点击查看活动详情”
第一题
题目理解
给出两个整数和,可以对和执行以下操作:
- 两个数都增加1
- 两个数都减去1(只能在时使用)
执行以下操作后的两个整数我们称为和,要使和的公因数最大,求出要达到这个结果要使用的最少操作步数
输入
输入整数,代表案例个数,
每个案例输入两个整数和,
输出
每个案例输出两个整数,第一个代表所有和变成的和的最大公因数的最大值,第二个代表达到这个结果要使用的最少操作步数
思路
一开始我就是想用暴力,想省事(抱着侥幸心理),但是结果肯定是不行的。那么我们又转到找规律的思路上去。在用暴力解的过程中,我发现那个最大公因数好像就是和的差的绝对值,那么情况就简单多了,我们就可以进行以下操作来进行判定:
- 把和的较小值赋到上,较大值赋到上
- 把和的其中一个拿过来作为判定基准,这里我们使用(较小值),设和的差的绝对值为
- 若已经是的因数,则步数为0
- 否则,则需判断两边的的倍数和倍数(我们不需要知道n是多少),然后看到哪一边的步数少,就取哪一边的步数作为答案
代码
#include<stdio.h>
#define in long long
//这里用c++是因为Java在长整型的处理性能上不如c++,这题用逻辑和思路一模一样的java代码就是大样例超时
int main()
{
in t;
scanf("%lld",&t);
while(t>0)
{
in a,b;
scanf("%lld %lld",&a,&b);
in x=a>b?a-b:b-a;//最大公因数
in y;
if(x==0||a-x==0||b-x==0)
{
y=0;
}
else
{
in d=x;
in e=a>b?a:b;
y=x-e>0?(x-e>e?e:x-e):(e%x>x-e%x?x-e%x:e%x);
}
printf("%lld %lld\n",x,y);
t--;
}
return 0;
}
第二题
题目理解
给出一个整数,要求找出一个特殊数组,其和为,数组如下:
- 设数组为,其中元素为,其取值有以下两种情况:
- 等于1
- 不等于1,但是数组中有取值为或者的元素
输入
输入整数,代表案例个数,
每个案例输入一个整数,
输出
每个案例输出一个整数——代表找出的特殊数组的长度
思路
不知道其他人会不会被这个题目带偏,反正我是被带偏了,一开始以为要根据和去找符合要求的数组元素,然后再把数组长度输出,实际上这样会把问题想复杂,我们不妨采用逆向思维:采用一套数组元素取值的模板去求这个数组的某个范围的元素的和,例如一个等差数列,若前项和刚好等于,那很省事,直接输出即可;若前项和大于,而前项和小于,这里是能不能用这个方法的核心,因为我们用的等差数列的公差是2,那意味着我们可以对数组中的元素做出调整,比如说最大的元素减一,然后第二大的元素减一,这么一直减下去直到有一个元素是2为止都可以,这样并不会导致数组中的元素的取值不符合要求。所以我们最担心的符合要求的问题就这样迎刃而解。
import java.util.Scanner;
public class Find_the_Array {
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();
for(int i=0;i<t;i++)
{
int s=sc.nextInt();
int n=1;
int sum=1;
int count=1;
while(s>sum)
{
n=n+2;
sum+=n;
count++;
}
System.out.println(count);
}
}
}