0
点赞
收藏
分享

微信扫一扫

(C++) 基于重载运算符的自动取模

金刚豆 2022-04-22 阅读 94
c++

文章目录

直接上代码

// #define int long long

#ifndef MOD
#define MOD 1e9+7
class Num {
private:
    static const int mod = MOD;
    int val = 0;

protected:
    static inline int norm(int x) {
        if (x < 0) {
            int cnt = abs(x)/mod + 1;
            x += mod*cnt;
        }
        return x%mod;
    }

    static int binPow(int base, int expo, int p) {
        if (expo == 0) {    // 防止 mod 1
            return 1 % p;
        }
        base %= p;
        int half = binPow(base, expo>>1, p);
        if (expo & 1) {
            return half*half%p * base%p;
        } else {
            return half*half%p;
        }
    }

public:
    Num() {}
    Num(int val):val(norm(val)) {}
    Num(const Num& num) {
        this->val = num.val;
    }

    ~Num() {}

    int getVal() {
        return this->val;
    }
    void setVal(const int val) {
        this->val = norm(val);
    }

    int& operator()() {
        return this->val;
    }

public:
    friend std::istream& operator>>(std::istream& cin, Num& num) {
        cin >> num.val;
        num.val = num.norm(num.val);
        return cin;
    }
    friend std::ostream& operator<<(std::ostream& cout, Num& num) {
        cout << num.val;
        return cout;
    }
    friend std::ostream& operator<<(std::ostream& cout, Num&& num) {
        cout << num.val;
        return cout;
    }

public:
    Num& operator+=(const Num& rhs) {
        val = norm(val + rhs.val);
        return *this;
    }
    Num& operator-=(const Num& rhs) {
        val = norm(val - rhs.val);
        return *this;
    }
    Num& operator*=(const Num& rhs) {
        val = norm(val * rhs.val);
        return *this;
    }
    Num& operator/=(const Num& rhs) {
        int inverseElement = binPow(rhs.val, mod-2, mod);
        val = norm(val * inverseElement);
        return *this;
    }

public:
    Num operator+() {
        Num tmp = val;
        return tmp;
    }
    Num operator-() {
        Num tmp = -val;
        return tmp;
    }

    friend Num operator+(const Num& lhs, const Num& rhs) {
        Num tmp = lhs;
        tmp += rhs;
        return tmp;
    }
    friend Num operator-(const Num& lhs, const Num& rhs) {
        Num tmp = lhs;
        tmp -= rhs;
        return tmp;
    }
    friend Num operator*(const Num& lhs, const Num& rhs) {
        Num tmp = lhs;
        tmp *= rhs;
        return tmp;
    }
    friend Num operator/(const Num& lhs, const Num& rhs) {
        Num tmp = lhs;
        tmp /= rhs;
        return tmp;
    }

public:
    Num operator++(signed) {   // 后置
        Num tmp = *this;
        val = norm(val+1);
        return tmp;
    }
    Num operator--(signed) {   // 后置
        Num tmp = *this;
        val = norm(val-1);
        return tmp;
    }
    Num& operator++() {   // 前置
        val = norm(val+1);
        return *this;
    }
    Num& operator--() {   // 前置
        val = norm(val-1);
        return *this;
    }

public:
    bool operator!() const {
        return val == 0;
    }
    bool operator==(const Num& rhs) const {
        return val == rhs.val;
    }
    bool operator!=(const Num& rhs) const {
        return val != rhs.val;
    }
    bool operator>(const Num& rhs) const {
        return val > rhs.val;
    }
    bool operator>=(const Num& rhs) const {
        return val >= rhs.val;
    }
    bool operator<(const Num& rhs) const {
        return val < rhs.val;
    }
    bool operator<=(const Num& rhs) const {
        return val <= rhs.val;
    }
    bool operator&&(const Num& rhs) const {
        return val && rhs.val;
    }
    bool operator||(const Num& rhs) const {
        return val || rhs.val;
    }

};
#endif // MOD

前言

在一些题目或情景中,需要我们对一个数进行取模运算,但是每次手动写取模会比较麻烦,因此就有了本文。

在C++,C#等语言中支持重载运算符,那么我们就可以自己写一个工具类,来满足自动取模的要求。

各部分介绍

宏定义

// #define int long long

#ifndef MOD
#define MOD 1e9+7
class Num {};
#endif // MOD

成员变量

private:
    static const int mod = MOD;
    int val = 0;

辅助函数

protected:
    static inline int norm(int x) {
        if (x < 0) {
            int cnt = abs(x)/mod + 1;
            x += mod*cnt;
        }
        return x%mod;
    }

    static int binPow(int base, int expo, int p) {
        if (expo == 0) {    // 防止 mod 1
            return 1 % p;
        }
        base %= p;
        int half = binPow(base, expo>>1, p);
        if (expo & 1) {
            return half*half%p * base%p;
        } else {
            return half*half%p;
        }
    }

构造和析构

public:
    Num() {}
    Num(int val):val(norm(val)) {}
    Num(const Num& num) {
        this->val = num.val;
    }

    ~Num() {}

get/set

public:
    int getVal() {
        return this->val;
    }
    void setVal(const int val) {
        this->val = norm(val);
    }

仿函数

public:
    int& operator()() {
        return this->val;
    }

标准输入输出

public:
    friend std::istream& operator>>(std::istream& cin, Num& num) {
        cin >> num.val;
        num.val = num.norm(num.val);
        return cin;
    }
    friend std::ostream& operator<<(std::ostream& cout, Num& num) {
        cout << num.val;
        return cout;
    }
    friend std::ostream& operator<<(std::ostream& cout, Num&& num) {
        cout << num.val;
        return cout;
    }

重载+= -= *= /=

public:
    Num& operator+=(const Num& rhs) {
        val = norm(val + rhs.val);
        return *this;
    }
    Num& operator-=(const Num& rhs) {
        val = norm(val - rhs.val);
        return *this;
    }
    Num& operator*=(const Num& rhs) {
        val = norm(val * rhs.val);
        return *this;
    }
    Num& operator/=(const Num& rhs) {
        int inverseElement = binPow(rhs.val, mod-2, mod);
        val = norm(val * inverseElement);
        return *this;
    }

重载+ - * /

public:
    Num operator+() {
        Num tmp = val;
        return tmp;
    }
    Num operator-() {
        Num tmp = -val;
        return tmp;
    }

    friend Num operator+(const Num& lhs, const Num& rhs) {
        Num tmp = lhs;
        tmp += rhs;
        return tmp;
    }
    friend Num operator-(const Num& lhs, const Num& rhs) {
        Num tmp = lhs;
        tmp -= rhs;
        return tmp;
    }
    friend Num operator*(const Num& lhs, const Num& rhs) {
        Num tmp = lhs;
        tmp *= rhs;
        return tmp;
    }
    friend Num operator/(const Num& lhs, const Num& rhs) {
        Num tmp = lhs;
        tmp /= rhs;
        return tmp;
    }

重载自增,自减运算符++ --

public:
    Num operator++(signed) {   // 后置
        Num tmp = *this;
        val = norm(val+1);
        return tmp;
    }
    Num operator--(signed) {   // 后置
        Num tmp = *this;
        val = norm(val-1);
        return tmp;
    }
    Num& operator++() {   // 前置
        val = norm(val+1);
        return *this;
    }
    Num& operator--() {   // 前置
        val = norm(val-1);
        return *this;
    }

重载比较、逻辑运算符

public:
    bool operator!() const {
        return val == 0;
    }
    bool operator==(const Num& rhs) const {
        return val == rhs.val;
    }
    bool operator!=(const Num& rhs) const {
        return val != rhs.val;
    }
    bool operator>(const Num& rhs) const {
        return val > rhs.val;
    }
    bool operator>=(const Num& rhs) const {
        return val >= rhs.val;
    }
    bool operator<(const Num& rhs) const {
        return val < rhs.val;
    }
    bool operator<=(const Num& rhs) const {
        return val <= rhs.val;
    }
    bool operator&&(const Num& rhs) const {
        return val && rhs.val;
    }
    bool operator||(const Num& rhs) const {
        return val || rhs.val;
    }

一些使用注意点

signed main () {

    Num num = 100;

    // 普通数值在左边不行
    // if (0 < num)
    if (num > 0) {
        vector<Num> arr(num()+1);
        /**
        	num * 114514
        	这里实际上是进行了类型转化
        	先将114514转化成Num类型的数据,再计算(if 中的 num > 0 也是)
        	可以在构造和析构中输出检验
        */ 
        iota(arr.begin(), arr.end(), num * 114514);
        cout << arr[num.getVal()] << endl;
    }

    system("pause");
    return 0;
}



END

举报

相关推荐

0 条评论