【问题标题】:long long int Declared Inside main()long long int 在 main() 内部声明
【发布时间】:2019-03-10 06:21:55
【问题描述】:

首都伯兰的剧院广场呈长方形 尺寸为 n × m 米。值此建城周年之际, 决定用方形花岗岩铺设广场 石板。每块石板的大小为a × a。

铺设广场最少需要多少块石板?它是 允许覆盖比剧院广场更大的表面,但 广场必须被覆盖。不允许打破石板。 石板的边应与广场的边平行。

输入

输入在第一行包含三个正整数: n, m and a (1 ≤  n, m, a ≤ 10^9).

输入给定:6 6 4

输出

写下所需数量的石板。

#include<stdio.h>
#include<math.h>
int main(){
    long long m, n, a;
    scanf("%lld %lld %lld", &m, &n, &a);
    long long req = ceil(m / a) * ceil(n / a);
    printf("%lld", req);    
}

它应该在第一个测试用例中给我4,但它给了我1。我看到了一个解决方案,人们使用int m, n, a 作为高于main() 的全局声明变量,在这种情况下,如果 10^18 在 4 字节全局声明变量中存储值(假设最后一个测试用例是非常大的数字)。或者当我们全局声明一个变量时是否有不同的规则?其中一些以main(m, n, a) 的身份传递,而没有在任何地方声明。

【问题讨论】:

  • 故障案例中的值是多少?
  • 请注意m / an / a 执行整数除法
  • 输入1000000000 1000000000 1输出-2147483648
  • 在我提到的第一种情况下,输入是6 6 4
  • @newby ceil(6/4) 是 1,因为 6/4 是 1。这就是整数除法的工作原理,它将结果截断为整数。 long long 是一个整数。

标签: c variables int


【解决方案1】:

你需要一个向上取整的整数除法。

int DivideRoundingUp(int numerator, int denominator)
{
    return (numerator+denominator-1) / denominator;
}

使用long long 而不是int 的版本应该提供正确的结果,参数最大为 10^9

【讨论】:

  • 这是一个很好的第一步,但是当m,n 很大时,long long req = DivideRoundingUp(m, a) * DivideRoundingUp(n, a); 将无法提供所需的结果..
【解决方案2】:

有了“(1 ≤  n, m, a ≤ 10^9)”,就不需要double数学或函数了。

由于m / a整数 除法-它会截断商的小数部分,使ceil(m / a) 无关紧要-简单地查找余数以查看是否应该“四舍五入”。

// long long req = ceil(m / a) * ceil(n / a);
long long m_over_a = m/a + (m%a != 0);
long long n_over_a = n/a + (n%a != 0);
long long req = m_over_a * n_over_a;  

注意m/am%a。在过去,编译器会执行 2 次昂贵的除法/余数计算。今天,期望一个好的编译器可以看到相邻的代码并一起执行单个 divide_and_remainder 计算是合理的。所以一旦m/a 完成,m%a 的成本通常是无关紧要的。

【讨论】:

    【解决方案3】:

    int/int 给出一个整数结果。为了避免在转换为 double 时可能发生的精度问题(尤其是从 64 位 long long 中),您应该检查除法的余数。

    long long req = (m / a + (m%a>0?1:0)) * (n / a +(n%a>0?1:0));
    

    【讨论】:

    • 您实际上并不需要ceil 函数。有条件地加 1 已经计算出上限。
    • 我将全局变量声明为 int 类型,我的问题仍然是 10^18 顺序的变量,但是当我在 main 内部声明为 int 而不是 long long 时,它显示运行时错误
    • int 中可以存储的最大变量是 2^31=2147483648 左右,long long 可以处理 2^63,但是如果你想能够解决输入问题:1000000000000000000(1E18) 10000000000000000000(1E18) 1,你必须实现自定义算术 - 答案是 10000000000000000000000000000000000000(1E36) - 超出长期范围。
    【解决方案4】:

    问题在于m/an/a的计算。

    因为mna都是整数类型,它们之间的除法执行整数除法,意思是和小数部分被截断。在您的示例中,您正在计算 6 / 4,由于此截断,其计算结果为 1。

    您需要将这些参数中的至少一个转换为浮点类型,例如 double 才能执行浮点除法:

    long long req = ceil((double)m / a) * ceil((double)n / a);
    

    【讨论】:

    • 好的,但是如果我将任何变量全局声明为 int,我可以在其中存储大量而不使用 long long
    • @newby int(或任何类型)具有固定大小,无论在何处定义。
    • 确实如此,但在这类问题中,通常可以通过适当使用整数算术来找到解决方案。 double 可能不准确,并且可能因“时间限制错误”而失败。
    • int n,m,a;main(){ scanf("%d%d%d",&amp;n,&amp;m,&amp;a); printf("%lld",(m+a-1ll)/a*((n+a-1)/a)); } 有人这样解决了这就是我问的原因
    • 这个答案已被接受,但他在全球范围内使用 int 但是当我在本地使用时,我没有通过最后一个非常大的测试用例
    猜你喜欢
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多