P1005 继续(3n+1)猜想
转跳点:🐏
┗|`O′|┛ 嗷~~,这个该死的猜想又来了,难度升级了,如过没写过 P1001 的建议先去看一下。话不多说,看题。
嗯,这道题就没有那么明确了,呃,也不能这么说,其实也挺明确。就是让你找出在输入样例中出现过但是没有在卡拉兹猜想演算过程中出现过的数。思路也很清晰,不用想的是,如果我们想知道哪个数没有出现,那么就得求出每一个卡拉兹猜想演算的过程出现的数,再记录下来。这个思路代表着我们无法减少卡拉兹计算次数,只能从存储和比较上做优化了,如果我每一个数都用数组把出现过的数都存起来,那么我们不仅浪费空间,而且找未出现的数的时候也十分浪费时间。为了减少时间与空间的成本,我们决定采用计数排序的思想来解决这个问题。
void Callatz(int num) { while (num != 1) { (num % 2) ? (num = (3 * num + 1) / 2) : (num /= 2); if (num <= 100) { FlagArray[num]++; // } } }
这是计数过程,我们开辟了一个数组,长度大于100,每一步演算过程出现的数都会被 FlagArray[num]++; 所记录 。当我们进行寻找的时候只需要,找出从数组FlagArray的1~n中找到为0 的数即可。
思路比较简单,实现起来有点麻烦
下面是代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define MAX_SIZE 110 4 int FlagArray[MAX_SIZE]; 5 void Callatz(int num); 6 int cmp(const void *a, const void *b); 7 8 int main() 9 { 10 int n; 11 int NumsArray[MAX_SIZE], ans[MAX_SIZE]; 12 scanf("%d", &n); 13 14 for (int i = 0; i < n; i++) 15 { 16 scanf("%d", &NumsArray[i]); 17 Callatz(NumsArray[i]); 18 } 19 int j = 0; 20 for (int i = 0; i < n; i++) 21 { 22 if (!FlagArray[NumsArray[i]]) 23 { 24 ans[j++] = NumsArray[i]; 25 printf("%d ", ans[j-1]); 26 } 27 } 28 putchar('\n'); 29 qsort(ans, j, sizeof(int), cmp); 30 for (int i = 0; i < j; i++) 31 { 32 printf("%s%d", i ? " " : "", ans[i]); 33 } 34 putchar('\n'); 35 36 return 0; 37 } 38 39 void Callatz(int num) 40 { 41 while (num != 1) 42 { 43 (num % 2) ? (num = (3 * num + 1) / 2) : (num /= 2); 44 if (num <= 100) 45 { 46 FlagArray[num]++; 47 } 48 } 49 } 50 51 int cmp(const void *a, const void *b) 52 { 53 return *(int *)b - *(int *)a; 54 }
——算法不易,诸君共勉!
大道五十,天衍四九,人遁其一!