C++ C++;竞争编程:在模N下简化表达式

C++ C++;竞争编程:在模N下简化表达式,c++,operator-overloading,operators,modulo,C++,Operator Overloading,Operators,Modulo,codechef上存在许多问题,需要对一些数字进行模运算 . 我碰巧为eg使用的每个算术运算符编写了%MOD- ans+=((sumX*sumZ)%MOD+(sumX+sumZ)%MOD)%MOD*Y)%MOD 现在有没有C++隐含的方法?< /p> 虽然说我们不能为内置类型重载算术运算符,但它们仍然可以通过任何方式使编写成为可能 它像ans+=(sumX*sumZ+(sumX+sumZ))*Y ?您可以创建一个表示数字与数量之比的小包装 template<typename Number,

codechef上存在许多问题,需要对一些数字进行模运算 . 我碰巧为eg使用的每个算术运算符编写了
%MOD
-

ans+=((sumX*sumZ)%MOD+(sumX+sumZ)%MOD)%MOD*Y)%MOD

<>现在有没有C++隐含的方法?< /p> 虽然说我们不能为内置类型重载算术运算符,但它们仍然可以通过任何方式使编写成为可能 它像
ans+=(sumX*sumZ+(sumX+sumZ))*Y

您可以创建一个表示数字与数量之比的小包装

template<typename Number, Number Width>
class ModuloArithmetic
{
  Number n;
public:
  ModuloArithmetic(Number n) : n(n % Width) {}
  Number get() const { return n; }

  ModuloArithmetic& operator+= (ModuloArithmetic other)
  { n = (n + other.get()) % Width; return *this; }

  // Other modifying operators 
};

template<typename Number, Number Width>
ModuloArithmetic<Number, Width> operator+(
  ModuloArithmetic<Number, Width> lhs,
  ModuloArithmetic<Number, Width> rhs) {
  return lhs.get() + rhs.get();
}

// And so forth for the other arithmetic operations.
模板
类模拟合法
{
数字n;
公众:
ModuleRoathmetic(数字n):n(n%宽度){}
Number get()常量{return n;}
ModulerAthMetic和运算符+=(ModulerAthMetic其他)
{n=(n+other.get())%Width;返回*this;}
//其他修改运算符
};
模板
模拟算子+(
模块模拟lhs,
模块模拟(rhs){
返回lhs.get()+rhs.get();
}
//对于其他算术运算,依此类推。
操作符总是处理包装类本身。因此,即使操作符没有显式地执行模运算,它也会在返回结果时“装箱”完成

然后,简单地用它来定义所有数字:

using num_t = ModuloArithmetic<int, MOD>;
num_t sumX, sumZ;
使用num\u t=modularorithmetic;
数一数二,数一数二;

多亏了@StoryTeller和@MSalters,我终于制作了这个片段,可以用来解决编码问题-

#define ll long long int
#define MOD 1000000007

template<typename Number, Number m>
class modNum
{
private:
    Number a;
public:
    // overloading '<<'
    friend ostream& operator<<(ostream& os, modNum const & num) {
          return os << num.a;
      }
    modNum(Number a) : a(a % m) {}

    Number get() const { return a; }

    modNum operator+= (modNum b){ a = (a + b.get()) % m; return a; }
    modNum operator*= (modNum b){ a = (a * b.get()) % m; return a; }
    modNum operator/= (modNum b){ a = (a / b.get()) % m; return a; }
    modNum operator-= (modNum b){ a = (a - b.get()) % m; return a; }
    modNum operator + (modNum b){modNum t = (a + b.get()) % m; return t;}
    modNum operator * (modNum b){modNum t = (a * b.get()) % m; return t;}
    modNum operator / (modNum b){modNum t = (a / b.get()) % m; return t;}
    modNum operator - (modNum b){modNum t = (a - b.get()) % m; return t;}

};
typedef modNum<ll, MOD> num_t;
//testing the code-
int int_max = 2147483647;
int sqroot_max = sqrt(int_max);

int main()
{
    num_t sumX(sqroot_max),sumZ(sqroot_max),Y(sqroot_max);
    cout<<(sumX*sumZ + sumX+sumZ)*Y;
    // (((sumX*sumZ) % MOD + (sumX + sumZ) % MOD) % MOD * Y) % MOD;
    return 0;
}
#定义ll long int
#定义MOD 100000007
模板
类模态数
{
私人:
a号;
公众:

//重载“当然,请创建您自己的类型并重载所有运算符以实现此行为。您可以编写一个自定义类型,如“my int”,并使用它。但是,通常需要一些样板文件,并将其替换为“Smart”运算符重写通常可能非常危险。那么您是否建议不要使用运算符重载?有没有其他方法可以简化上述表达式的编写?@Udayradeshmukh:问题不在于运算符重载本身。这只是命名函数的一种奇特方式。危险在于正确实现它们。您通常不能假定基础C++类型与原始数学相同。比如说,使用<代码>未签名< /C> >,然后代码> **b%c<代码>实际上是<代码> A*B%~0U%C。并且签名<代码> int >代码>在溢出时有未定义的行为。@ UdayrajDeshmukh:中间有。假设(使数学变得容易)~0u是255,MOD=254。现在253+253 MOD 254=252。但是首先有一个溢出:253+253=250,250 MOD 254是250。当
MOD>INT\u MAX/2
时,这已经有问题了。加法可能会溢出中间结果。@MSalters-是的,但是没有包装器也是一个风险。我想,OP是真实的m的合理宽度。尽管与数值限制相比,在宽度上添加静态_断言可能是可行的。