1005. 继续(3n+1)猜想 (25)
时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CHEN, Yue
卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。
当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对n=3进行验证的时候,我们需要计算3、5、8、4、2、1,则当我们对n=5、8、4、2进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这4个数已经在验证3的时候遇到过了,我们称5、8、4、2是被3“覆盖”的数。我们称一个数列中的某个数n为“关键数”,如果n不能被数列中的其他数字所覆盖。
现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。
输入格式:每个测试输入包含1个测试用例,第1行给出一个正整数K(<100),第2行给出K个互不相同的待验证的正整数n(1<n<=100)的值,数字间用空格隔开。
输出格式:每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用1个空格隔开,但一行中最后一个数字后没有空格。
输入样例:6
3 5 6 7 8 11
输出样例:
7 6
以上是原题,以下是分析:
①分析3n+1的基本算法:
f(n)=n/2 (n为偶数)
(3*n+1)/2 (n为奇数)
②所谓覆盖,就是指3->5->8->4->2->1
以上从左往右是覆盖关系,如3覆盖5
所以,只需保存两数之间的覆盖数3。
③接着分析一下题目输入、输出:
3 5 6 7 8 11
显然6->3->5->8 7->11,所以3 5 8 11不作考虑,而输出6 7
④下面是算法问题(我的算法,可能不是最好的):
1,用一个数组保存所有数
2,从左往右n[i]判断是否与n[0~n-1]是覆盖关系
如果是,被覆盖数置0;否则继续。
//这里覆盖关系是有先后顺序之分的
3,排序
4,打印结果(反复置0之后,最终不为0的就是关键数)
下面是伪代码
boolean check(int a, int b)
{
//b做3n+1运算,直至a==b或b==1
return a==b;
}
void main()
{
//1,输入K,输入K个整数,并用数组保存
//2,调用check方法,判断是否为覆盖关系,如果是,被覆盖数置0;否则继续
for(int i=0 ; i<K ; i++)
{
for(int j=i+1 ; j<K ; j++)
{
if(check(n[i], n[j])) n[i]=0; //n[i]数被覆盖
else if(check(n[j], n[i])) n[j]=0; //n[j]数被覆盖
}
}
//3,排序
//4,打印结果
}
//Java
package package1; import java.util.Arrays; import java.util.Scanner; public class PAT1005 { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int K = scan.nextInt(); int[] n = new int[K]; for (int i = 0; i < K; i++) n[i] = scan.nextInt(); // Work int count = 0; for (int i = 0; i < K; i++) { for (int j = i + 1; j < K; j++) { if (n[i] * n[j] == 0) continue; if (check(n[i], n[j])) { n[i] = 0; count++; } else if (check(n[j], n[i])) { n[j] = 0; count++; } } } Arrays.sort(n); for (int i = K - 1; i >= count + 1; i--) System.out.print(n[i] + " "); System.out.print(n[count]); } // a: Being checked, b: Checker public static boolean check(int a, int b) { while (a != 1 && b != 1 && a != b) { b = (b % 2 == 0 ? b / 2 : (3 * b + 1) / 2); } return a == b; } }
//C语言
<span style="font-family:Microsoft YaHei;font-size:24px;">#include<stdio.h> int check(int, int); void bubble_sort(int[], int); int main() { int K, i, j; scanf("%d", &K); int n[K]; for (i = 0; i < K; i++) scanf("%d", &n[i]); // Work int count = 0; for (i = 0; i < K; i++) for (j = i + 1; j < K; j++) { if (n[i] * n[j] == 0) continue; if (check(n[i], n[j])) { n[i] = 0; count++; } else if (check(n[j], n[i])) { n[j] = 0; count++; } } //Sort bubble_sort(n, K); for (i = K - 1; i >= count + 1; i--) printf("%d ", n[i]); printf("%d", n[count]); return 0; } // a: Being checked, b: Checker int check(int a, int b) { while (a != 1 && b != 1 && a != b) b = (b % 2 == 0 ? b / 2 : (3 * b + 1) / 2); return a == b; } void bubble_sort(int a[], int len) { int i, j, temp; for(i=0 ; i<len ; i++) for(j=i+1 ; j<len ; j++) if(a[i]>a[j]) { temp = a[i]; a[i] = a[j]; a[j] = temp; } }</span>