C++ 使用模运算的正确方法

C++ 使用模运算的正确方法,c++,c,math,C++,C,Math,在一次编程竞赛中,我被要求用100000007取模 下面的代码显示了我是如何实现它的 #include <stdio.h> #define ll long long #define MOD 1000000007 ll getmin(ll a, ll b){return (a<b)?a:b;} void solve(){ ll a,b,c,Tv; scanf("%lld %lld %lld",&a,&b,&c); Tv = ((a

在一次编程竞赛中,我被要求用100000007取模

下面的代码显示了我是如何实现它的

#include <stdio.h>
#define ll long long
#define MOD 1000000007
ll getmin(ll a, ll b){return (a<b)?a:b;}

void solve(){
    ll a,b,c,Tv;
    scanf("%lld %lld %lld",&a,&b,&c);
    Tv = ((a%MOD)*(b%MOD)*(c%MOD))%MOD;
    ll sideofcube = getmin(a,getmin(b,c));
    ll numofcube = 0;
    ll smallvol = ((sideofcube%MOD)*(sideofcube%MOD)*(sideofcube%MOD))%MOD;
    numofcube = Tv/smallvol;
    printf("%lld %lld\n",sideofcube,numofcube);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        solve();
    }
    return 0;
}
我的回答是否定的

100000000 -1
这里出了什么问题?我在乘法之前就已经取了MOD。

一个%MOD*b%MOD*c%MOD的乘积可以溢出一个64位整数。为避免此问题,一次只能将两个项相乘:

    Tv = ((a % MOD) * (b % MOD)) % MOD;
    Tv = ((Tv) * (c % MOD)) % MOD;
此外,您还应为ll使用typedef:

在这种情况下,两项乘积只需要60位log2100000007*100000007,因此乘积不会溢出并变为负值。您可能希望使用64位无符号整数ull或uint64,因为它在某些系统上可能更快。

a%MOD*b%MOD*c%MOD的乘积可能会使64位整数溢出。为避免此问题,一次只能将两个项相乘:

    Tv = ((a % MOD) * (b % MOD)) % MOD;
    Tv = ((Tv) * (c % MOD)) % MOD;
此外,您还应为ll使用typedef:


在这种情况下,两项乘积只需要60位log2100000007*100000007,因此乘积不会溢出并变为负值。您可能希望使用64位无符号整数ull或uint64\t,因为在某些系统上它可能更快。

乘法的问题是,在您有机会应用到模运算之前,它通常会溢出。虽然已经有了答案。请不要这么做。这会导致很多问题。。。如果必须为long-long-int使用另一个名称,则使用typedef-long-long-int-ll;至少,要避免与宏相关pitfalls@EdHeal如果我使用define,会出现什么问题呢?长宏是一种钝武器。任何出现的ll将被替换。这使得调试更加棘手。这使得阅读代码更加困难。等此外,ll看起来像11乘法的问题是,在你有机会应用模运算之前,它通常会溢出。虽然已经有了答案。请不要这么做。这会导致很多问题。。。如果必须为long-long-int使用另一个名称,则使用typedef-long-long-int-ll;至少,要避免与宏相关pitfalls@EdHeal如果我使用define,会出现什么问题呢?长宏是一种钝武器。任何出现的ll将被替换。这使得调试更加棘手。这使得阅读代码更加困难。等另外,我看起来很好的解释,谢谢。当我开始学习新概念时,总是感觉很好。还有一个疑问。在我的代码中,我还使用了除法。在处理这样的模化值时,这是一种直接的划分方法吗?@ USS324399——对于正或无符号数,C或C++余数运算符%是可以的。要正确处理正数和负数,如果余数不是零,并且与除数符号不同,请将除数添加到余数中。这将产生一个适当的数学模,其中结果为零或与除数具有相同的符号。@user3243499-根据编译器的不同,可以使用乘法和移位序列而不是除法来实现%by常量,但这是一个内部细节。如果有兴趣,请看。很好的解释,谢谢。当我开始学习新概念时,总是感觉很好。还有一个疑问。在我的代码中,我还使用了除法。在处理这样的模化值时,这是一种直接的划分方法吗?@ USS324399——对于正或无符号数,C或C++余数运算符%是可以的。要正确处理正数和负数,如果余数不是零,并且与除数符号不同,请将除数添加到余数中。这将产生一个适当的数学模,其中结果为零或与除数具有相同的符号。@user3243499-根据编译器的不同,可以使用乘法和移位序列而不是除法来实现%by常量,但这是一个内部细节。如果感兴趣,请查看。
typedef long long ll;