a905448839 发表于 2023-5-4 22:38:11

被难麻了,来个高手

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

我的代码:
#include<stdio.h>
void sum(long long n,int *p);
void sum(long long n,int *p)
{
        int i = 20;
        while(n)
        {
                p = n%10;
                n /= 10;
                i--;
        }
       
}

void PD(int *pn,int *pt);
void PD(int *pn,int *pt)
{
        int n,m;
       
        for(n = 0;n < 21; n++)
        {
                for(m = 0;m < 21; m++)
                {
                        if(pt == pn)
                        {
                                pt = 100;
                                pn = 100;
                               
                                continue;
                        }
                }
        }

}

void Print(int *p);
void Print(int *p)
{
        int t = 1;
        int n;
       
        for(n = 0;n < 21;n++)
        {
                if(t && p == 0)
                continue;
                printf("%d",p);
                t = 0;
               
        }
        printf("\n");
}




int main()
{
        unsigned long long n,two_n;
        int pn = {0};
        int pt = {0};
        int i;


        scanf("%lld",&n);
        two_n = 2*n;
       
        sum(n,pn);
        sum(two_n,pt);
       
       
        int demo_pt;
        for(i = 0;i < 21;i++)
        {
                demo_pt = pt;
        }
       
        PD(pn,demo_pt);
       

//        Print(pn);
//        Print(pt);
//        Print(demo_pt);
       
        for(i = 0;i < 21; i++)
        {
                if(demo_pt != 100 && pn != 100)
                {
                        printf("No\n");
                        Print(pt);
                        return 0;
                }
        }
       
        printf("Yes\n");
        Print(pt);

        return 0;
}


提示错误:

歌者文明清理员 发表于 2023-5-4 22:40:14

本帖最后由 歌者文明清理员 于 2023-5-4 22:46 编辑

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

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>

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

void to_num(int num[], char str[]) {
    int i;
    if (num == -1) {
      str = '-';
      i = 1;
    } else {
      for (i = 20; i >= 0 && !num; i--); // 找到最高位非零的位置
    }
    if (i < 0) {
      str = '0';
      str = '\0';
      return;
    }
    for (int j = i; j >= 0; j--) {
      str == -1)] = num + '0'; // 从高位到低位输出
    }
    str == -1)] = '\0';
}

bool is_permutation(int a[], int b[]) {
    int count = {0};
    bool same_number = false;
    for (int i = 0; i < 21; i++) {
      count]++;
      if (b != a) {
            same_number = false;
      }
      count]--;
    }
    for (int i = 1; i <= 9; i++) {
      if (count != 0) {
            return false;
      }
    }
    return !same_number;
}

int main() {
    char str;
    int n = {0}, two_n = {0};

    scanf("%s", str);
    to_array(str, n);

    // 判断输入是否为0
    if (n == 0) {
      printf("Yes\n0\n");
      return 0;
    }

    // 计算2n
    unsigned long long carry = 0;
    for (int i = 1; i <= 20; i++) {
      two_n = (n * 2 + carry) % 10;
      carry = (n * 2 + carry) / 10;
    }
    two_n = carry;

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

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

    return 0;
}

isdkz 发表于 2023-5-4 22:42:51

您的代码基本正确,但有一些细节上的问题,例如程序中的函数命名不够清晰。下面是您的代码的一个优化版本,对函数名进行了改进,并进行了一些细节调整。

#include <stdio.h>

void fill_digit_array(long long n, int *p);
void remove_common_digits(int *pn, int *pt);
void print_digits(int *p);

void fill_digit_array(long long n, int *p)
{
    int i = 20;
    while (n)
    {
      p = n % 10;
      n /= 10;
      i--;
    }
}

void remove_common_digits(int *pn, int *pt)
{
    int n, m;

    for (n = 0; n < 21; n++)
    {
      for (m = 0; m < 21; m++)
      {
            if (pt == pn)
            {
                pt = 100;
                pn = 100;
                continue;
            }
      }
    }
}

void print_digits(int *p)
{
    int t = 1;
    int n;

    for (n = 0; n < 21; n++)
    {
      if (t && p == 0)
            continue;
      printf("%d", p);
      t = 0;
    }
    printf("\n");
}

int main()
{
    unsigned long long n, two_n;
    int pn = {0};
    int pt = {0};
    int i;

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

    fill_digit_array(n, pn);
    fill_digit_array(two_n, pt);

    int demo_pt;
    for (i = 0; i < 21; i++)
    {
      demo_pt = pt;
    }

    remove_common_digits(pn, demo_pt);

    for (i = 0; i < 21; i++)
    {
      if (demo_pt != 100 && pn != 100)
      {
            printf("No\n");
            print_digits(pt);
            return 0;
      }
    }

    printf("Yes\n");
    print_digits(pt);

    return 0;
}


此代码首先计算输入数值的两倍,然后将它们转换为整数数组。之后,从这两个数组中移除所有相同的数字。如果所有数字都被移除,说明两个数值具有相同的数字组成,只是排列不同。根据这一条件,输出“Yes”或“No”,并打印出加倍后的数值。

a905448839 发表于 2023-5-4 23:15:20

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



输入9999999999999999999不对

fc1735 发表于 2023-5-5 05:11:24

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int cmp(const void *a, const void *b) { return *(char*)a - *(char*)b; }
#define MAX_SIZE 20
int main() {
char orig, doubled; scanf("%s", orig);
char buff = {'0',};
for (int i = strlen(orig); i > 0; i--) {
    int n = (orig - '0') * 2 + buff;
    buff += n / 10;
    buff = n % 10 + '0';
}
char *res = buff > '0' ? buff : buff + 1;
strcpy(doubled, res);
qsort(orig, strlen(orig), sizeof(char), cmp);
qsort(res, strlen(res), sizeof(char), cmp);
puts(strcmp(orig, res) == 0 ? "Yes" : "No");
puts(doubled);
}

歌者文明清理员 发表于 2023-5-5 16:47:56

问题解决了饿吗

a905448839 发表于 2023-5-5 17:25:18

歌者文明清理员 发表于 2023-5-5 16:47
问题解决了饿吗

还没呢,你可以看一下我的新帖

a905448839 发表于 2023-5-5 17:27:18

歌者文明清理员 发表于 2023-5-5 16:47
问题解决了饿吗

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

https://fishc.com.cn/forum.php?mod=viewthread&tid=227896&extra=&mobile=2
页: [1]
查看完整版本: 被难麻了,来个高手