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]獨特的樹葉

具體做法請等待後續博客,這裏粘個用這個寫的哈希代碼(比自然溢出慢一點,但能過,模數用109+710^9+7可以過,998244353998244353不行!):

#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;
}

用模數類:
用模數類
自然溢出:
自然溢出

綜上:有被卡常的風險!可能需要雙哈希!作者不對此代碼負責!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章