之前怎么也想不明白最大公约数的解法,终于想清楚了,顺便写出来,万一有人需要呢,对吧。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
Main Solution = new Main();
int t=sc.nextInt();
int ans;
for(int i=0;i<t;i++){
int n=sc.nextInt();
// 调用方法1
ans = Solution.solution_2(n);
// 调用方法2
System.out.println(ans);
}
}
/**
* 暴力法
*/
private int solution_1(int n){
int N = 4*n;
boolean[] mark=new boolean[N];
// 首先把起点标记一下
mark[0] = true;
int m=0,ans=1;
// 循环查找下一个标记的点
while (mark[(m+n+1)%N] != true){
m += n+1;
m = m%N;
mark[m]=true;
ans++;
}
// 加上最后一次重复标记的点
return ans + 1;
}
/**
* 最大公约数的解法
*/
private int solution_2(int n){
int d=gcd(4*n, n+1);
int ans=(4*n)/d;
return ans + 1;
}
public int gcd(int a, int b){
int r;
while(b != 0){
r = a % b;
a = b;
b = r;
}
return a;
}
}
最大公约数解法的解释:
首先,第一次重合的点一定是起点。
Why?由于小王必须从起点出发,假设我们第一次重合的点是A点,即A点一定要被打卡两次,也就是说,一定存在一条路径,是从 起点->A点(第一次到达) 的。
假设我们再一次到达了A点,训练结束。那么,也一定还存在一条路径,是从起点(再一次遇见)->A(再一次打卡)的,即,要想到达A点,就一定会先过起点。这样就说明,起点一定是比A点更早的重复打卡,即:A点是最早重合的点,这个假设不成立。
然后,就是打卡多少次的问题了。
由于一定是要走圈的整数倍,所以可以easy得到一个等式, x⋅(4∗n)=y⋅(n+1) 这里的这个y
就是我们要的答案。要使得y
最小,即要求 y⋅(n+1) 等于 4*n
和n+1
的最小公倍数。设g
为最大公约数,h
为最小公倍数,则有: [(4∗n)⋅(n+1)]=g∗h , 且 h=y⋅(n+1)
则答案为:y=[(4∗n)⋅(n+1)]g⋅(n+1)=4∗ng
同样的,这里的最终答案忘了计算起点(第一次打卡),所以要加1