简体   繁体   English

将一个数分解为两个数的和

[英]Breaking a number into the sum of two numbers

I have a problem with a such a task:我对这样的任务有问题:

Write a program that finds such a pair of numbers x and y that their sum is equal to n.编写一个程序,找出这样一对数字 x 和 y,它们的和等于 n。 In addition, the pair of numbers should meet the following conditions:此外,这对数字还应满足以下条件:

  • the number x has at least 2 digits,数字 x 至少有 2 位数字,
  • the number y is one digit less than the number x.数字 y 比数字 x 少一位。

N is from the range <10 ; N 来自 <10 的范围; 10^5> 10^5>

for number 80, the output should look like this:对于数字 80,输出应如下所示:

79 + 1 = 80
78 + 2 = 80
77 + 3 = 80
76 + 4 = 80
75 + 5 = 80
74 + 6 = 80
73 + 7 = 80
72 + 8 = 80
71 + 9 = 80

I wrote a code that works in most cases but the system rejects the solution when testing the number 100000, because the program does not find such pairs - the test requires 9000 such pairs.我写了一个在大多数情况下都可以工作的代码,但是在测试数字 100000 时系统拒绝了解决方案,因为程序没有找到这样的对 - 测试需要 9000 个这样的对。 I can't understand what's wrong because I think the program is okay.我不明白出了什么问题,因为我认为程序没问题。 I'd like to ask for some advice.我想请教一些建议。

My code:我的代码:

#include <stdio.h>
#include <math.h>

int digit_count(int n)
{
    int i = 0;
    while (n > 0)
    {
        n /= 10;
        i++;
    }
    return i;
}

int breakdown(int n)
{
    long n_digits = digit_count(n), check = 0, count = 1;
    long double y_max = pow(10, (n_digits - 1)) - 1, y_min = (pow(10, (n_digits - 2)));

    for (int i = (int)y_min; i <= (int)y_max; i++)
    {
        if (digit_count(n - i) >= 2 && digit_count(i)+1 == digit_count(n - 1))
        {
            printf("%d + %d = %d          %d\n", n - i, i, n, count);
            check = 1;
            count++;
        }
    }

    if (check == 0)
    {
        printf("Nothing to show.");
    }
    return 0;
}

int main(void)
{
    unsigned int n = 0;
    printf("Podaj N: ");
    if (1 != scanf("%u", &n))
    {
        printf("Incorrect input");
        return 1;
    }
    if (n > 1000000 || n < 10)
    {
        printf("Incorrect input");
        return 1;
    }

    breakdown(n);
    return 0;
}

PS: I forgot to mention that the count variable is here only for debugging PS:忘了说count变量这里只是为了调试

I solved the problem in this way.我以这种方式解决了这个问题。 Now it works for all numbers in the range according to the task.现在它根据任务适用于范围内的所有数字。

#include <stdio.h>
#include <math.h>

int digit_count(int n)
{
    int i = 0;
    while (n > 0)
    {
        n /= 10;
        i++;
    }
    return i;
}

int breakdown(int n)
{
    int n_digits = digit_count(n), check = 0;
    double y_max = pow(10, n_digits - 1) - 1; 
    //int i = 0 instead of i = y_min = (pow(10, (n_digits - 2))
    for (int i = 0; i <= (int)y_max; i++)
    {
        //instead of if (digit_count(n - i) >= 2 && digit_count(i)+1 == digit_count(n - i))
        if (digit_count(n - i) >= 2 && digit_count(n - i) == digit_count(i) + 1) 
        {
            printf("%d + %d = %d\n", n - i, i, n);
            check = 1;
        }
    }

    if (check == 0)
    {
        printf("Nothing to show.");
    }
    return 0;
}

int main(void)
{
    unsigned int n = 0;
    printf("Podaj N: ");
    if (1 != scanf("%u", &n))
    {
        printf("Incorrect input");
        return 1;
    }
    if (n > 1000000 || n < 10)
    {
        printf("Incorrect input");
        return 1;
    }

    breakdown(n);
    return 0;
}

The posted code checks all the numbers in [10 k - 2 , 10 k - 1 - 1], k beeing the number of digits of n , using the expansive (and wrong) condition张贴的代码检查所有的数字[10的k - 2,10的k - 1 - 1],K beeing的数字数量n ,使用膨胀(和错误的)条件

if (digit_count(n - i) >= 2 && digit_count(i)+1 == digit_count(n - 1)) { /* ... */ }
//                                                                 ^

You can solve the problem avoiding all (or at least most of) those digits counts, by carefully calculating the valid extents of the ranges of the x and y values.通过仔细计算xy值范围的有效范围,您可以解决避免所有(或至少大部分)这些数字计数的问题。

The following is a possible implementation下面是一个可能的实现

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>

static inline long min_(long a, long b)
{
    return b < a ? b : a;   
}

static inline long max_(long a, long b)
{
    return b < a ? a : b;   
}

int digit_count(long n);

// Specilization for integer exponent. 
long pow_10_(int exponent);

// A little helper struct
typedef struct range_s
{
    long begin, end;
} range_t;

// Shrinks the range of the y values so that all the x = z - y are valid
// (the right nummber of digits and less than z).
range_t find_range(long z, long x_0)
{
    range_t y = {max_(1, x_0 / 10), x_0};
    range_t x = {x_0, min_(z, x_0 * 10)};

    long x_1 = z - y.begin;
    if (x_1 < x.begin)
        y.end = y.begin;
    else if (x_1 >= x.end)
        y.begin = min_(z - x.end + 1, y.end);

    long x_2 = z - y.end;
    if (x_2 > x.end)
        y.begin = y.end;
    else if (x_2 <= x.begin)
        y.end = max_(z - x.begin + 1, y.begin);

    return y;
}

long print_sums(long z, range_t y);

long breakdown(long z)
{
    int n_digits = digit_count(z); // <- Only once.

    long x_0 = pow_10_(n_digits - 1);

    // Depending on z, the x values may have the same number of digits of z or
    // one less. 
    long count = 0;
    if (n_digits > 2)
    {
        count += print_sums(z, find_range(z, x_0 / 10));
    }
    count += print_sums(z, find_range(z, x_0));
    return count;
}

int main(void)
{
    long n = 0;
    if (1 != scanf("%lu", &n))
    {
        printf("Incorrect input");
        return 1;
    }
    if (n > 1000000 || n < 10)
    {
        printf("Incorrect input");
        return 1;
    }

    printf("\nCount: %ld\n", breakdown(n));
    return 0;
}

int digit_count(long n)
{
    int i = 0;
    while (n > 0)
    {
        n /= 10;
        i++;
    }
    return i ? i : 1;  // I consider 0 a 1-digit number.
}

long pow_10_(int exponent)
{
    if (exponent < 0)
        return 0;
    long result = 1;
    while (exponent-- > 0)
        result *= 10;
    return result;
}

#define SAMPLES 5

long print_sums(long z, range_t y)
{
    for (long i = y.begin; i < y.end; ++i)
#ifndef SHOW_ONLY_SAMPLES
        printf("%ld + %ld = %ld\n", z - i, i, z);
#else
        if ( i < y.begin + SAMPLES - 1 || i > y.end - SAMPLES )
            printf("%ld + %ld = %ld\n", z - i, i, z);
        else if ( i == y.begin + SAMPLES )
            puts("...");
#endif
    return  y.end - y.begin;  
}

Testable here .在这里测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM