题目描述:数组
卡拉兹(Callatz)猜测已经在1001中给出了描述。在这个题目里,状况稍微有些复杂。 当咱们验证卡拉兹猜测的时候,为了不重复计算,能够记录下递推过程当中遇到的每个数。例如对 n=3 进行验证的时候,咱们须要计算 三、五、八、四、二、1,
则当咱们对 n=五、八、四、2 进行验证的时候,就能够直接断定卡拉兹猜测的真伪,而不须要重复计算,由于这 4 个数已经在验证3的时候遇到过了,
咱们称 五、八、四、2 是被 3“覆盖”的数。咱们称一个数列中的某个数 n 为“关键数”,若是 n 不能被数列中的其余数字所覆盖。 如今给定一系列待验证的数字,咱们只须要验证其中的几个关键数,就能够没必要再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。 输入格式: 每一个测试输入包含 1 个测试用例,第 1 行给出一个正整数 K (<100),第 2 行给出 K 个互不相同的待验证的正整数 n (1<n≤100)的值,数字间用空格隔开。 输出格式: 每一个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用 1 个空格隔开,但一行中最后一个数字后没有空格。
输入样例: 6 3 5 6 7 8 11 输出样例: 7 6
主要思想:测试
利用一个数组,初始置零,用于标记某个数字是否为关键数; 并在运算过程当中添加一个计数器,记录关键数的个数; 最后,倒序遍历数组,若是标记为1则打印输出关键字。
本人代码:spa
// Guess Number from 3*n+1 -> 1 // Go ahead // 这种解法(22/25) 最后一个测试点过不去 // 上述问题已经解决,在代码 47行,48行给出了部分解释 /* 当咱们验证卡拉兹猜测的时候,为了不重复计算, 能够记录下递推过程当中遇到的每个数。例如对 n=3 进行验证的时候, 咱们须要计算 三、五、八、四、二、1,则当咱们对 n=五、八、四、2 进行验证的时候, 就能够直接断定卡拉兹猜测的真伪,而不须要重复计算, 由于这 4 个数已经在验证3的时候遇到过了, 咱们称 五、八、四、2 是被 3“覆盖”的数。咱们称一个数列中的某个数 n 为“关键数”, 若是 n 不能被数列中的其余数字所覆盖。 如今给定一系列待验证的数字,咱们只须要验证其中的几个关键数, 就能够没必要再重复验证余下的数字。 你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。 */ # include <stdio.h> int main(void) { int k; // 输入一个整数 k<100 int n, temp; int i; int table[101] = {0}; // 记录数据是否出现 (不用再单独排序) // 定义为300 不会出现数组越界的状况 int val = 0; // 记录 最终table 中有多少个不为零的数 scanf("%d",&k); for (i=0; i<k; i++) { scanf("%d",&temp); table[temp] = 1; } for (i=1; i<=100; i++) { // 若是此数字在table中出现过,则进行运算 if (1 == table[i]) { n = i; while(n>1) { if (n%2 == 0) n = n/2; else n = ((3*n)+1)/2; // 若是此处写 n = 3*n+1 则会在最后一个测试点没法经过,没有仔细的看数字猜测过程,(3*n+1)/2 // 判断计算过程当中的数是否在输入数组中出现 // 注:在提交过程当中 若是直接判断 table[n] (n==100)可能会出现数组越界的状况 if (n<=100 && n>=2) { table[n] = 0; } } } } // 输出table中不为0 的下标的个数 for (i=100; i>=1; i--) { if (1 == table[i]) val++; } for (i=100; i>=1; i--) { if (1==table[i]) { printf("%d",i); val--; if (val != 0) printf(" "); } } return 0; }