C++自动取模的模数类

一直想写,今天终于写出来了。

使用方法:ModNumber<MOD> k,可以定义一个模MOD意义下的变量k,它接下来的所有运算都自动模MOD,不需要再手写。

具体操作方法请自行探索:

#define int long long

template<const int _MOD> struct ModNumber{
    int x;
    ModNumber(){x=0;}
    ModNumber(LL y){x=y%_MOD;}
    int Int(){return x;}
    int Pow(int y){
        int ret=1,tmp=x;
        while(y){
            if(y&1)
                ret=((LL)ret*tmp)%_MOD;
            y>>=1;
            tmp=((LL)tmp*tmp)%_MOD;
        }
        return ret;
    }
    void operator = (LL y){x=y%_MOD;}
    bool operator == (LL y) const{return x==y;}
    bool operator == (ModNumber y) const{return x==y.x;}
    bool operator != (LL y) const{return x!=y;}
    bool operator != (ModNumber y) const{return x!=y.x;}
    bool operator < (LL y) const{return x<y;}
    bool operator < (ModNumber y) const{return x<y.x;}
    bool operator > (LL y) const{return x>y;}
    bool operator > (ModNumber y) const{return x>y.x;}
    bool operator <= (LL y) const{return x<=y;}
    bool operator <= (ModNumber y) const{return x<=y.x;}
    bool operator >= (LL y) const{return x>=y;}
    bool operator >= (ModNumber y) const{return x>=y.x;}
    ModNumber operator + (ModNumber y) const{return ((LL)x+y.x)%_MOD;}
    ModNumber operator * (ModNumber y) const{
        return ((LL)x*y.x)%_MOD;
    }
    ModNumber operator - (ModNumber y) const{return ((x-y.x)%_MOD+_MOD)%_MOD;}
    ModNumber operator + (LL y) const{return ((LL)x+y)%_MOD;}
    ModNumber operator * (LL y) const{return ((LL)x*y)%_MOD;}
    ModNumber operator - (LL y) const{return ((x-y)%_MOD+_MOD)%_MOD;}
    void operator += (ModNumber y){*this=*this+y;}
    void operator *= (ModNumber y){*this=*this*y;}
    void operator -= (ModNumber y){*this=*this-y;}
    void operator += (LL y){x=((LL)x+y)%_MOD;}
    void operator *= (LL y){x=((LL)x*y)%_MOD;}
    void operator -= (LL y){x=((x-y)%_MOD+_MOD)%_MOD;}
    ModNumber operator ^ (int y){
        ModNumber ret=Pow(y);
        return ret;
    }
    ModNumber operator / (ModNumber y) const{
        return ((LL)x*(y.Pow(_MOD-2)))%_MOD;
    }
    void operator /= (ModNumber y){*this=*this/y;}
    template<class T> friend bool operator == (T y,ModNumber t){return y==t.x;}
    template<class T> friend ModNumber operator + (T t,ModNumber y){return ((LL)t+y.x)%_MOD;}
    template<class T> friend ModNumber operator * (T t,ModNumber y){return ((LL)t*y.x)%_MOD;}
    template<class T> friend ModNumber operator - (T t,ModNumber y){return ((t-y.x)%_MOD+_MOD)%_MOD;}
    template<class T> friend ModNumber operator / (T t,ModNumber y){return ModNumber((y/t).Pow(_MOD-2));}
    ModNumber operator / (int y) const{return ((LL)x*(ModNumber(y).Pow(_MOD-2)))%_MOD;}
    void operator /= (int y){*this=*this/y;}
    void operator ++ (){*this=*this+1;}
    void operator -- (){*this=*this-1;}
    void operator ++ (int k){*this=*this+1;}
    void operator -- (int k){*this=*this-1;}
};

例题:(树哈希)BZOJ4754 [Jsoi2016]独特的树叶

具体做法请等待后续博客,这里粘个用这个写的哈希代码(比自然溢出慢一点,但能过,模数用 1 0 9 + 7 10^9+7 109+7可以过, 998244353 998244353 998244353不行!):

#include<set>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;

#define LL long long

template<const int _MOD> struct ModNumber{
    int x;
    ModNumber(){x=0;}
    ModNumber(LL y){x=y%_MOD;}
    int Int(){return x;}
    int Pow(int y){
        int ret=1,tmp=x;
        while(y){
            if(y&1)
                ret=((LL)ret*tmp)%_MOD;
            y>>=1;
            tmp=((LL)tmp*tmp)%_MOD;
        }
        return ret;
    }
    void operator = (LL y){x=y%_MOD;}
    bool operator == (LL y) const{return x==y;}
    bool operator == (ModNumber y) const{return x==y.x;}
    bool operator != (LL y) const{return x!=y;}
    bool operator != (ModNumber y) const{return x!=y.x;}
    bool operator < (LL y) const{return x<y;}
    bool operator < (ModNumber y) const{return x<y.x;}
    bool operator > (LL y) const{return x>y;}
    bool operator > (ModNumber y) const{return x>y.x;}
    bool operator <= (LL y) const{return x<=y;}
    bool operator <= (ModNumber y) const{return x<=y.x;}
    bool operator >= (LL y) const{return x>=y;}
    bool operator >= (ModNumber y) const{return x>=y.x;}
    ModNumber operator + (ModNumber y) const{return ((LL)x+y.x)%_MOD;}
    ModNumber operator * (ModNumber y) const{
        return ((LL)x*y.x)%_MOD;
    }
    ModNumber operator - (ModNumber y) const{return ((x-y.x)%_MOD+_MOD)%_MOD;}
    ModNumber operator + (LL y) const{return ((LL)x+y)%_MOD;}
    ModNumber operator * (LL y) const{return ((LL)x*y)%_MOD;}
    ModNumber operator - (LL y) const{return ((x-y)%_MOD+_MOD)%_MOD;}
    void operator += (ModNumber y){*this=*this+y;}
    void operator *= (ModNumber y){*this=*this*y;}
    void operator -= (ModNumber y){*this=*this-y;}
    void operator += (LL y){x=((LL)x+y)%_MOD;}
    void operator *= (LL y){x=((LL)x*y)%_MOD;}
    void operator -= (LL y){x=((x-y)%_MOD+_MOD)%_MOD;}
    ModNumber operator ^ (int y){
        ModNumber ret=Pow(y);
        return ret;
    }
    ModNumber operator / (ModNumber y) const{
        return ((LL)x*(y.Pow(_MOD-2)))%_MOD;
    }
    void operator /= (ModNumber y){*this=*this/y;}
    template<class T> friend bool operator == (T y,ModNumber t){return y==t.x;}
    template<class T> friend ModNumber operator + (T t,ModNumber y){return ((LL)t+y.x)%_MOD;}
    template<class T> friend ModNumber operator * (T t,ModNumber y){return ((LL)t*y.x)%_MOD;}
    template<class T> friend ModNumber operator - (T t,ModNumber y){return ((t-y.x)%_MOD+_MOD)%_MOD;}
    template<class T> friend ModNumber operator / (T t,ModNumber y){return ModNumber((y/t).Pow(_MOD-2));}
    ModNumber operator / (int y) const{return ((LL)x*(ModNumber(y).Pow(_MOD-2)))%_MOD;}
    void operator /= (int y){*this=*this/y;}
    void operator ++ (){*this=*this+1;}
    void operator -- (){*this=*this-1;}
    void operator ++ (int k){*this=*this+1;}
    void operator -- (int k){*this=*this-1;}
};

#define MAXN 100000
#define ULL ModNumber<1000000007>
//懒得改以前的代码所以直接把#define ULL long long改成了#define ULL ModNumber<1000000007>

ULL P[MAXN+5];
struct TreeHash{
    int N;
    int Size[MAXN+5];
    vector<int> G[MAXN+5];
    ULL Hash[MAXN+5],Up[MAXN+5],Down[MAXN+5];
    void Init(int n){
        N=n;
        for(int i=1;i<N;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
    }
    void Dfs1(int u,int fa){
        for(int i=0;i<int(G[u].size());i++){
            int v=G[u][i];
            if(v!=fa){
                Dfs1(v,u);
                Size[u]+=Size[v];
                Down[u]+=P[Size[v]]*Down[v];
            }
        }
        Size[u]++;
        Down[u]++;
    }
    void Dfs2(int u,int fa){
        Up[u]=P[N-Size[u]]*(Up[fa]+Down[fa]-Down[u]*P[Size[u]]);
        Hash[u]=Down[u]+Up[u];
        for(int i=0;i<int(G[u].size());i++){
            int v=G[u][i];
            if(v!=fa)
                Dfs2(v,u);
        }
    }
    void GetHash(){
        Dfs1(1,-1);
        Dfs2(1,-1);
    }
}A,B;

set<ULL> S;

int main(){
    int N;
    scanf("%d",&N);
    srand(998244353);
    for(int i=1;i<=N;i++)
        P[i]=rand();
    A.Init(N),A.GetHash();
    B.Init(N+1),B.GetHash();
    for(int i=1;i<=N;i++)
        S.insert(A.Hash[i]);
    for(int i=1;i<=N+1;i++)
        if(B.G[i].size()==1)
           if(S.count(B.Hash[B.G[i][0]]-P[1]))
                return printf("%d\n",i),0;
}

用模数类:
用模数类
自然溢出:
自然溢出

综上:有被卡常的风险!可能需要双哈希!作者不对此代码负责!!

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值