这个c代码有啥问题?
Posted
技术标签:
【中文标题】这个c代码有啥问题?【英文标题】:What's wrong in this c code?这个c代码有什么问题? 【发布时间】:2016-02-02 15:51:34 【问题描述】:这是一个关于 Codeforces 的问题,link
在片段[a , b]
上找出k-整除 个数。换句话说,您需要找到a ≤ x ≤ b
和x
可以被k
整除的整数值x
的数量。
输入:
唯一一行包含三个空格分隔的整数k
、a
和b
(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
、-30
、30
【讨论】:
【参考方案2】:这是一道数学题,真的。我们有
1 ≤ k ≤ 101860 -1018 ≤ a ≤ b ≤ 1018
所以我们需要inttypes.h
和int64_t
才能描述a 和b;它也适用于k。要扫描这三个值,模式"%" SCNd64 " %" SCNd64 " %d" SCNd64 ""
将起作用。要打印,请使用模式"%" PRId64 ""
。 (包含这些的 inttypes.h
头文件在 ISO C99 中标准化,也在 POSIX 中定义。)
手头的实际问题是找到唯一整数n
的数量
a ≤ n k ≤ b
其中a和b是整数,k是正整数。最小和最大 n 满足
a ≤ nmin kb ≥ n最大 k
也可以写成
a ÷ k ≤ nmin 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-k 到 b+k 的数字,包括在内。由于int64_t
可以表示(大致)-9.22×1018 到 +9.22×1018 的范围,因此我们可以很好地覆盖。
对于实际的解决方案,你需要扫描a、b、k(我已经提到了@987654335的正确模式@),验证a≤b且k≥1,计算nmax和 nmin 使用上面的数学,最后打印结果(再次,我提到了用于int64_t
的 printf 模式)。如果您牢牢掌握数学,这非常简单。
【讨论】:
以上是关于这个c代码有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章