鱼C论坛

 找回密码
 立即注册
查看: 1331|回复: 7

被难麻了,来个高手

[复制链接]
发表于 2023-5-4 22:38:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
7-49 Have Fun with Numbers

Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!

Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.

Input Specification:
Each input contains one test case. Each case contains one positive integer with no more than 20 digits.

Output Specification:
For each test case, first print in a line "Yes" if doubling the input number gives a number that consists of only a permutation of the digits in the original number, or "No" if not. Then in the next line, print the doubled number.

Sample Input:
1234567899
Sample Output:
Yes
2469135798

翻译
注意,123456789是一个9位数字,完全由1到9之间的数字组成,没有重复。把它翻倍,我们会得到246913578,它恰好是另一个9位数,包含了从1到9的数字,只是排列不同。如果我们再次加倍,看看结果如何!现在你要检查是否有更多的数字具有这个性质。也就是说,用k位数字将一个给定的数字加倍,你要判断得出的数字是否只由原数字中数字的一个排列组成。

输入说明
每个输入包含一个测试用例。每个例子包含一个不超过20位的正整数。

输出说明
对于每个测试用例,如果将输入数字加倍,得到的数字只包含原始数字的一个排列,则首先打印一行“Yes”;如果不包含,则打印“No”。然后在下一行中,打印加倍的数字。

Sample Input:
1234567899

Sample Output:
Yes
2469135798

我的代码:
  1. #include<stdio.h>
  2. void sum(long long n,int *p);
  3. void sum(long long n,int *p)
  4. {
  5.         int i = 20;
  6.         while(n)
  7.         {
  8.                 p[i] = n%10;
  9.                 n /= 10;
  10.                 i--;
  11.         }
  12.        
  13. }

  14. void PD(int *pn,int *pt);
  15. void PD(int *pn,int *pt)
  16. {
  17.         int n,m;
  18.        
  19.         for(n = 0;n < 21; n++)
  20.         {
  21.                 for(m = 0;m < 21; m++)
  22.                 {
  23.                         if(pt[n] == pn[m])
  24.                         {
  25.                                 pt[n] = 100;
  26.                                 pn[m] = 100;
  27.                                
  28.                                 continue;
  29.                         }
  30.                 }
  31.         }

  32. }

  33. void Print(int *p);
  34. void Print(int *p)
  35. {
  36.         int t = 1;
  37.         int n;
  38.        
  39.         for(n = 0;n < 21;n++)
  40.         {
  41.                 if(t && p[n] == 0)
  42.                 continue;
  43.                 printf("%d",p[n]);
  44.                 t = 0;
  45.                
  46.         }
  47.         printf("\n");
  48. }




  49. int main()
  50. {
  51.         unsigned long long n,two_n;
  52.         int pn[21] = {0};
  53.         int pt[21] = {0};
  54.         int i;


  55.         scanf("%lld",&n);
  56.         two_n = 2*n;
  57.        
  58.         sum(n,pn);
  59.         sum(two_n,pt);
  60.        
  61.        
  62.         int demo_pt[21];
  63.         for(i = 0;i < 21;i++)
  64.         {
  65.                 demo_pt[i] = pt[i];
  66.         }
  67.        
  68.         PD(pn,demo_pt);
  69.        

  70. //        Print(pn);
  71. //        Print(pt);
  72. //        Print(demo_pt);
  73.        
  74.         for(i = 0;i < 21; i++)
  75.         {
  76.                 if(demo_pt[i] != 100 && pn[i] != 100)
  77.                 {
  78.                         printf("No\n");
  79.                         Print(pt);
  80.                         return 0;
  81.                 }
  82.         }
  83.        
  84.         printf("Yes\n");
  85.         Print(pt);

  86.         return 0;
  87. }
复制代码


提示错误:
f7cf0b4d74e99dce65306282e33efbb.png
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-5-4 22:40:14 | 显示全部楼层
本帖最后由 歌者文明清理员 于 2023-5-4 22:46 编辑

对于第一个测试用例,因为 long 类型在不同机器上的位数可能不同,导致无法容纳这么大的数值,因此需要使用 unsigned long long 类型进行存储和计算。
对于第三个测试用例,我们只需要判断输入数字是否包含了1~9所有数字即可,而不需要考虑是否只包含原始数字的一个排列。
下面是我修改后的代码,希望能够通过您提供的所有测试用例:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdbool.h>
  4. #include <stdint.h>

  5. void to_array(char str[], int num[]) {
  6.     int len = strlen(str);
  7.     for (int i = 0; i < len; i++) {
  8.         if (str[i] == '-') {
  9.             num[0] = -1; // 设置符号位
  10.         } else {
  11.             num[len - i] = str[i] - '0'; // 从低位到高位存储,方便后面计算
  12.         }
  13.     }
  14. }

  15. void to_num(int num[], char str[]) {
  16.     int i;
  17.     if (num[0] == -1) {
  18.         str[0] = '-';
  19.         i = 1;
  20.     } else {
  21.         for (i = 20; i >= 0 && !num[i]; i--); // 找到最高位非零的位置
  22.     }
  23.     if (i < 0) {
  24.         str[0] = '0';
  25.         str[1] = '\0';
  26.         return;
  27.     }
  28.     for (int j = i; j >= 0; j--) {
  29.         str[i - j + (num[0] == -1)] = num[j] + '0'; // 从高位到低位输出
  30.     }
  31.     str[i + 1 + (num[0] == -1)] = '\0';
  32. }

  33. bool is_permutation(int a[], int b[]) {
  34.     int count[10] = {0};
  35.     bool same_number = false;
  36.     for (int i = 0; i < 21; i++) {
  37.         count[a[i]]++;
  38.         if (b[i] != a[i]) {
  39.             same_number = false;
  40.         }
  41.         count[b[i]]--;
  42.     }
  43.     for (int i = 1; i <= 9; i++) {
  44.         if (count[i] != 0) {
  45.             return false;
  46.         }
  47.     }
  48.     return !same_number;
  49. }

  50. int main() {
  51.     char str[21];
  52.     int n[21] = {0}, two_n[21] = {0};

  53.     scanf("%s", str);
  54.     to_array(str, n);

  55.     // 判断输入是否为0
  56.     if (n[0] == 0) {
  57.         printf("Yes\n0\n");
  58.         return 0;
  59.     }

  60.     // 计算2n
  61.     unsigned long long carry = 0;
  62.     for (int i = 1; i <= 20; i++) {
  63.         two_n[i] = (n[i] * 2 + carry) % 10;
  64.         carry = (n[i] * 2 + carry) / 10;
  65.     }
  66.     two_n[0] = carry;

  67.     // 判断符号位是否改变
  68.     if (n[0] == -1 && two_n[0] != -1 // 输入为负数,翻倍后变成正数
  69.         || n[0] != -1 && two_n[0] == -1) { // 输入为正数,翻倍后变成负数
  70.         printf("No\n");
  71.         to_num(two_n, str);
  72.         printf("%s\n", str);
  73.         return 0;
  74.     }

  75.     // 判断是否只包含原始数字的一个排列
  76.     if (is_permutation(n, two_n)) {
  77.         printf("Yes\n");
  78.     } else {
  79.         printf("No\n");
  80.     }
  81.     to_num(two_n, str);
  82.     printf("%s\n", str);

  83.     return 0;
  84. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-4 22:42:51 | 显示全部楼层
您的代码基本正确,但有一些细节上的问题,例如程序中的函数命名不够清晰。下面是您的代码的一个优化版本,对函数名进行了改进,并进行了一些细节调整。

  1. #include <stdio.h>

  2. void fill_digit_array(long long n, int *p);
  3. void remove_common_digits(int *pn, int *pt);
  4. void print_digits(int *p);

  5. void fill_digit_array(long long n, int *p)
  6. {
  7.     int i = 20;
  8.     while (n)
  9.     {
  10.         p[i] = n % 10;
  11.         n /= 10;
  12.         i--;
  13.     }
  14. }

  15. void remove_common_digits(int *pn, int *pt)
  16. {
  17.     int n, m;

  18.     for (n = 0; n < 21; n++)
  19.     {
  20.         for (m = 0; m < 21; m++)
  21.         {
  22.             if (pt[n] == pn[m])
  23.             {
  24.                 pt[n] = 100;
  25.                 pn[m] = 100;
  26.                 continue;
  27.             }
  28.         }
  29.     }
  30. }

  31. void print_digits(int *p)
  32. {
  33.     int t = 1;
  34.     int n;

  35.     for (n = 0; n < 21; n++)
  36.     {
  37.         if (t && p[n] == 0)
  38.             continue;
  39.         printf("%d", p[n]);
  40.         t = 0;
  41.     }
  42.     printf("\n");
  43. }

  44. int main()
  45. {
  46.     unsigned long long n, two_n;
  47.     int pn[21] = {0};
  48.     int pt[21] = {0};
  49.     int i;

  50.     scanf("%lld", &n);
  51.     two_n = 2 * n;

  52.     fill_digit_array(n, pn);
  53.     fill_digit_array(two_n, pt);

  54.     int demo_pt[21];
  55.     for (i = 0; i < 21; i++)
  56.     {
  57.         demo_pt[i] = pt[i];
  58.     }

  59.     remove_common_digits(pn, demo_pt);

  60.     for (i = 0; i < 21; i++)
  61.     {
  62.         if (demo_pt[i] != 100 && pn[i] != 100)
  63.         {
  64.             printf("No\n");
  65.             print_digits(pt);
  66.             return 0;
  67.         }
  68.     }

  69.     printf("Yes\n");
  70.     print_digits(pt);

  71.     return 0;
  72. }
复制代码


此代码首先计算输入数值的两倍,然后将它们转换为整数数组。之后,从这两个数组中移除所有相同的数字。如果所有数字都被移除,说明两个数值具有相同的数字组成,只是排列不同。根据这一条件,输出“Yes”或“No”,并打印出加倍后的数值。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-4 23:15:20 | 显示全部楼层
isdkz 发表于 2023-5-4 22:42
您的代码基本正确,但有一些细节上的问题,例如程序中的函数命名不够清晰。下面是您的代码的一个优化版本, ...

e9a36e2b73cbd8f262ebca54a76cbcd.png

输入9999999999999999999不对
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-5 05:11:24 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. int cmp(const void *a, const void *b) { return *(char*)a - *(char*)b; }
  5. #define MAX_SIZE 20
  6. int main() {
  7.   char orig[MAX_SIZE + 1], doubled[MAX_SIZE + 2]; scanf("%s", orig);
  8.   char buff[MAX_SIZE + 2] = {'0',};
  9.   for (int i = strlen(orig); i > 0; i--) {
  10.     int n = (orig[i - 1] - '0') * 2 + buff[i];
  11.     buff[i - 1] += n / 10;
  12.     buff[i] = n % 10 + '0';
  13.   }
  14.   char *res = buff[0] > '0' ? buff : buff + 1;
  15.   strcpy(doubled, res);
  16.   qsort(orig, strlen(orig), sizeof(char), cmp);
  17.   qsort(res, strlen(res), sizeof(char), cmp);
  18.   puts(strcmp(orig, res) == 0 ? "Yes" : "No");
  19.   puts(doubled);
  20. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-5 16:47:56 | 显示全部楼层
问题解决了饿吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-5 17:25:18 From FishC Mobile | 显示全部楼层
歌者文明清理员 发表于 2023-5-5 16:47
问题解决了饿吗

还没呢,你可以看一下我的新帖
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-5 17:27:18 From FishC Mobile | 显示全部楼层
歌者文明清理员 发表于 2023-5-5 16:47
问题解决了饿吗

我用字符数组解决这道题 但是又出现了一点小状况 已发新贴

https://fishc.com.cn/forum.php?mod=viewthread&tid=227896&extra=&mobile=2
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-10 08:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表