C++ 竞争性编程:简化模 N 下的表达式
C++ competitive programming : Simplifying expressions under modulo N
codechef 上有很多问题需要对某个数字进行模运算
like in this one。我碰巧为用于例如 -
的每个算术运算符写 % MOD
ans += (((sumX*sumZ) % MOD + (sumX + sumZ) % MOD) % MOD * Y) % MOD;
现在在 C++ 中有什么方法可以隐式地做到这一点吗?
虽然this answer说我们不能为内置类型重载算术运算符,但他们仍然有任何方法可以编写
喜欢 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.
运营商总是处理包装器 class 本身。因此,即使运算符未明确执行模运算,也会在 return 上完成 "boxing" 结果。
然后用它来定义你所有的号码就很简单了:
using num_t = ModuloArithmetic<int, MOD>;
num_t sumX, sumZ;
感谢@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;
}
codechef 上有很多问题需要对某个数字进行模运算 like in this one。我碰巧为用于例如 -
的每个算术运算符写% MOD
ans += (((sumX*sumZ) % MOD + (sumX + sumZ) % MOD) % MOD * Y) % MOD;
现在在 C++ 中有什么方法可以隐式地做到这一点吗?
虽然this answer说我们不能为内置类型重载算术运算符,但他们仍然有任何方法可以编写
喜欢 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.
运营商总是处理包装器 class 本身。因此,即使运算符未明确执行模运算,也会在 return 上完成 "boxing" 结果。
然后用它来定义你所有的号码就很简单了:
using num_t = ModuloArithmetic<int, MOD>;
num_t sumX, sumZ;
感谢@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;
}