【问题标题】:What's wrong in this c code?这个c代码有什么问题?
【发布时间】:2016-02-02 15:51:34
【问题描述】:

这是一个关于 Codeforces 的问题,link

在片段[a , b] 上找出k-整除 个数。换句话说,您需要找到a ≤ x ≤ bx 可以被k 整除的整数值x 的数量。

输入:
唯一一行包含三个空格分隔的整数kab
(1 ≤ k ≤ 1018;  -1018 ≤ a ≤ b ≤ 1018)。

输出:
打印所需的号码。

下面是我的源代码:

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

int count(int k,int a, int b)
{
   if(a>b)
      return 0;

   if(a%k!=0)
      return count(k,a+1,b);

   return 1+count(k,a+1,b);
}

int main()
{
    int k,a,b,counter;
    scanf("%d%d%d",&k,&a,&b);

    if(k==0)
       counter=0;
    else
       counter=count(k,a,b);

    printf("%d",counter);

    return 0;
}

现在,问题是当我提交我的代码时,我收到了这个回复wrong answer at test 57。所以,如果有人可以帮助我找出问题所在。

【问题讨论】:

  • 缩进很差的代码,看起来更像一道数学题而不是 C。
  • - 1018 ≤ a ≤ b ≤ 1018 注意负数!模数运算可能会令人惊讶。

标签: c algorithm integer integer-division


【解决方案1】:

我宁愿使用 for 循环:

for (int i = a; i < b; ++i) {
    if ((i % k) == 0) {
        printf("%d can be divided by %d\n", i, k);
        ++counter;
    }
}
printf("There are %d numbers divisible by %d between %d and %d\n", counter, k, a, b);

将输出:

-28 can be divided by 7
-21 can be divided by 7
-14 can be divided by 7
-7 can be divided by 7
0 can be divided by 7
7 can be divided by 7
14 can be divided by 7
21 can be divided by 7
28 can be divided by 7
There are 9 numbers divisible by 7 between -30 and 30

如果您输入:7-3030

【讨论】:

    【解决方案2】:

    这是一道数学题,真的。我们有

    1 ≤ k ≤ 101860
    -1018ab ≤ 1018

    所以我们需要inttypes.hint64_t 才能描述ab;它也适用于k。要扫描这三个值,模式"%" SCNd64 " %" SCNd64 " %d" SCNd64 "" 将起作用。要打印,请使用模式"%" PRId64 ""。 (包含这些的 inttypes.h 头文件在 ISO C99 中标准化,也在 POSIX 中定义。)

    手头的实际问题是找到唯一整数n 的数量

    an kb

    其中ab是整数,k是正整数。最小和最大 n 满足

    anmin k
    bn最大 k

    也可以写成

    a ÷ knmin
    b ÷ k ≥ nmax

    其中÷ 表示普通除法。我们需要打印的数字是唯一n的个数,或者

    nmax - nmin + 1

    如果我们使用/ 进行整数除法(如在C 中所做的那样,即截断除法),ceil() 用于ceil(向正无穷大舍入),floor() 用于 floor (向负无穷舍入),我们记得 k 是一个正整数,我们可以将不等式写成

    a ÷ k ≤ ceil( a ÷ k ) = nmin
    b ÷ k ≥ floor( b ÷ k ) = n最大

    要打印的数字是

    地板(b÷k)-天花板(a÷k)+1

    虽然标准 C 库在 math.h 中提供了函数 ceil()floor(),但它们仅适用于浮点数(但即使是双精度浮点数也没有 -10 范围内的整数精度18 到 +1018)。相反,我们需要使用整数舍入“技巧”:

    ceil( x ÷ k ) = (x + k - 1) / k , x > 0, k > 0
    ceil( x ÷ k ) = x / k, x ≤ 0, k > 0

    地板(x ÷ k )= x / k, x ≥ 0, k > 0
    地板(x ÷ k ) = (x - k + 1) / k,   x k > 0

    这里唯一的限制是我们的整数类型必须能够表示从 a-kb+k 的数字,包括在内。由于int64_t 可以表示(大致)-9.22×1018 到 +9.22×1018 的范围,因此我们可以很好地覆盖。

    对于实际的解决方案,你需要扫描abk(我已经提到了@987654335的正确模式@),验证abk≥1,计算nmaxnmin 使用上面的数学,最后打印结果(再次,我提到了用于int64_t 的 printf 模式)。如果您牢牢掌握数学,这非常简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-16
      • 2015-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多