这个c代码有啥问题?

Posted

技术标签:

【中文标题】这个c代码有啥问题?【英文标题】: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 注意负数!模数运算可能会令人惊讶。 ^ 好点。例如:***.com/a/11720841/2757035 【参考方案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 kbn最大 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 模式)。如果您牢牢掌握数学,这非常简单。

【讨论】:

以上是关于这个c代码有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章

CMapX添加一个点,下面的代码有啥有关问题

C ++这两个代码制作对象数组有啥区别?

有啥工具可以为 Windows 目标编译 C++2011 代码?

VC/C++ 裸属性有啥作用?

逗号运算符有啥作用?

@synchronized() 作为目标 C 中的单例方法有啥作用?