一直想寫,今天終於寫出來了。
使用方法: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]獨特的樹葉
具體做法請等待後續博客,這裏粘個用這個寫的哈希代碼(比自然溢出慢一點,但能過,模數用可以過,不行!):
#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;
}
用模數類:
自然溢出: