鱼C论坛

 找回密码
 立即注册
查看: 805|回复: 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

我的代码:
#include<stdio.h>
void sum(long long n,int *p);
void sum(long long n,int *p)
{
        int i = 20;
        while(n)
        {
                p[i] = 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[n] == pn[m])
                        {
                                pt[n] = 100;
                                pn[m] = 100;
                                
                                continue;
                        }
                }
        }

}

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




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


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

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

        return 0;
}

提示错误:
f7cf0b4d74e99dce65306282e33efbb.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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[i] == '-') {
            num[0] = -1; // 设置符号位
        } else {
            num[len - i] = str[i] - '0'; // 从低位到高位存储,方便后面计算
        }
    }
}

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

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

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

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

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

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

    // 判断符号位是否改变
    if (n[0] == -1 && two_n[0] != -1 // 输入为负数,翻倍后变成正数
        || n[0] != -1 && two_n[0] == -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;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[i] = 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[n] == pn[m])
            {
                pt[n] = 100;
                pn[m] = 100;
                continue;
            }
        }
    }
}

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

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

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

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

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

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

    remove_common_digits(pn, demo_pt);

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

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

    return 0;
}

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

使用道具 举报

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

e9a36e2b73cbd8f262ebca54a76cbcd.png

输入9999999999999999999不对
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[MAX_SIZE + 1], doubled[MAX_SIZE + 2]; scanf("%s", orig);
  char buff[MAX_SIZE + 2] = {'0',};
  for (int i = strlen(orig); i > 0; i--) {
    int n = (orig[i - 1] - '0') * 2 + buff[i];
    buff[i - 1] += n / 10;
    buff[i] = n % 10 + '0';
  }
  char *res = buff[0] > '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);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-5 16:47:56 | 显示全部楼层
问题解决了饿吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

还没呢,你可以看一下我的新帖
想知道小甲鱼最近在做啥?请访问 -> 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
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-28 01:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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