#pragma once
#include"../hashmap/hashmap.hpp"
#include"../internal/internal-math.hpp"// a^x = b (mod p) である最小の非負整数 x を返すint64_tmod_log(int64_ta,int64_tb,int64_tp){if((a%=p)<0)a+=p;if((b%=p)<0)b+=p;int64_tf,g,r=1%p;for(f=0;(g=gcd(a,p))>1;++f){if(b%g)return(r==b)?f:-1;b/=g;p/=g;(r*=(a/g))%=p;}if(p==1)returnf;int64_tir=internal::inv(r,p);(b*=ir)%=p;int64_tk=0,ak=1;HashMap<int64_t,int64_t>baby;for(;k*k<p;++k){if(baby.find(ak)==baby.end())baby[ak]=k;(ak*=a)%=p;}int64_tiak=internal::inv(ak,p);for(int64_ti=0;i<k;++i){if(baby.find(b)!=baby.end())returnf+i*k+baby[b];(b*=iak)%=p;}return-1;}
#line 2 "modulo/mod-log.hpp"
#line 2 "hashmap/hashmap.hpp"
#line 2 "hashmap/hashmap-base.hpp"
#include<cstdint>usingnamespacestd;namespaceHashMapImpl{usingu32=uint32_t;usingu64=uint64_t;template<typenameKey,typenameData>structHashMapBase;template<typenameKey,typenameData>structitrB:iterator<bidirectional_iterator_tag,Data,ptrdiff_t,Data*,Data&>{usingbase=iterator<bidirectional_iterator_tag,Data,ptrdiff_t,Data*,Data&>;usingptr=typenamebase::pointer;usingref=typenamebase::reference;u32i;HashMapBase<Key,Data>*p;explicitconstexpritrB():i(0),p(nullptr){}explicitconstexpritrB(u32_i,HashMapBase<Key,Data>*_p):i(_i),p(_p){}explicitconstexpritrB(u32_i,constHashMapBase<Key,Data>*_p):i(_i),p(const_cast<HashMapBase<Key,Data>*>(_p)){}friendvoidswap(itrB&l,itrB&r){swap(l.i,r.i),swap(l.p,r.p);}friendbooloperator==(constitrB&l,constitrB&r){returnl.i==r.i;}friendbooloperator!=(constitrB&l,constitrB&r){returnl.i!=r.i;}constrefoperator*()const{returnconst_cast<constHashMapBase<Key,Data>*>(p)->data[i];}refoperator*(){returnp->data[i];}ptroperator->()const{return&(p->data[i]);}itrB&operator++(){assert(i!=p->cap&&"itr::operator++()");do{i++;if(i==p->cap)break;if(p->occupied_flag[i]&&!p->deleted_flag[i])break;}while(true);return(*this);}itrBoperator++(int){itrBit(*this);++(*this);returnit;}itrB&operator--(){do{i--;if(p->occupied_flag[i]&&!p->deleted_flag[i])break;assert(i!=0&&"itr::operator--()");}while(true);return(*this);}itrBoperator--(int){itrBit(*this);--(*this);returnit;}};template<typenameKey,typenameData>structHashMapBase{usingu32=uint32_t;usingu64=uint64_t;usingiterator=itrB<Key,Data>;usingitr=iterator;protected:template<typenameK>inlineu64randomized(constK&key)const{returnu64(key)^r;}template<typenameK,enable_if_t<is_same<K,Key>::value,nullptr_t>=nullptr,enable_if_t<is_integral<K>::value,nullptr_t>=nullptr>inlineu32inner_hash(constK&key)const{return(randomized(key)*11995408973635179863ULL)>>shift;}template<typenameK,enable_if_t<is_same<K,Key>::value,nullptr_t>=nullptr,enable_if_t<is_integral<decltype(K::first)>::value,nullptr_t>=nullptr,enable_if_t<is_integral<decltype(K::second)>::value,nullptr_t>=nullptr>inlineu32inner_hash(constK&key)const{u64a=randomized(key.first),b=randomized(key.second);a*=11995408973635179863ULL;b*=10150724397891781847ULL;return(a+b)>>shift;}template<typenameK,enable_if_t<is_same<K,Key>::value,nullptr_t>=nullptr,enable_if_t<is_integral<typenameK::value_type>::value,nullptr_t>=nullptr>inlineu32inner_hash(constK&key)const{staticconstexpru64mod=(1LL<<61)-1;staticconstexpru64base=950699498548472943ULL;u64res=0;for(auto&elem:key){__uint128_tx=__uint128_t(res)*base+(randomized(elem)&mod);res=(x&mod)+(x>>61);}__uint128_tx=__uint128_t(res)*base;res=(x&mod)+(x>>61);if(res>=mod)res-=mod;returnres>>(shift-3);}template<typenameD=Data,enable_if_t<is_same<D,Key>::value,nullptr_t>=nullptr>inlineu32hash(constD&dat)const{returninner_hash(dat);}template<typenameD=Data,enable_if_t<is_same<decltype(D::first),Key>::value,nullptr_t>=nullptr>inlineu32hash(constD&dat)const{returninner_hash(dat.first);}template<typenameD=Data,enable_if_t<is_same<D,Key>::value,nullptr_t>=nullptr>inlineKeydata_to_key(constD&dat)const{returndat;}template<typenameD=Data,enable_if_t<is_same<decltype(D::first),Key>::value,nullptr_t>=nullptr>inlineKeydata_to_key(constD&dat)const{returndat.first;}voidreallocate(u32ncap){vector<Data>ndata(ncap);vector<bool>nf(ncap);shift=64-__lg(ncap);for(u32i=0;i<cap;i++){if(occupied_flag[i]&&!deleted_flag[i]){u32h=hash(data[i]);while(nf[h])h=(h+1)&(ncap-1);ndata[h]=move(data[i]);nf[h]=true;}}data.swap(ndata);occupied_flag.swap(nf);cap=ncap;occupied=s;deleted_flag.resize(cap);fill(std::begin(deleted_flag),std::end(deleted_flag),false);}inlineboolextend_rate(u32x)const{returnx*2>=cap;}inlineboolshrink_rate(u32x)const{returnHASHMAP_DEFAULT_SIZE<cap&&x*10<=cap;}inlinevoidextend(){reallocate(cap<<1);}inlinevoidshrink(){reallocate(cap>>1);}public:u32cap,s,occupied;vector<Data>data;vector<bool>occupied_flag,deleted_flag;u32shift;staticu64r;staticconstexpruint32_tHASHMAP_DEFAULT_SIZE=4;explicitHashMapBase():cap(HASHMAP_DEFAULT_SIZE),s(0),occupied(0),data(cap),occupied_flag(cap),deleted_flag(cap),shift(64-__lg(cap)){}itrbegin()const{u32h=0;while(h!=cap){if(occupied_flag[h]&&!deleted_flag[h])break;h++;}returnitr(h,this);}itrend()const{returnitr(this->cap,this);}frienditrbegin(constHashMapBase&h){returnh.begin();}frienditrend(constHashMapBase&h){returnh.end();}itrfind(constKey&key)const{u32h=inner_hash(key);while(true){if(occupied_flag[h]==false)returnthis->end();if(data_to_key(data[h])==key){if(deleted_flag[h]==true)returnthis->end();returnitr(h,this);}h=(h+1)&(cap-1);}}boolcontain(constKey&key)const{returnfind(key)!=this->end();}itrinsert(constData&d){u32h=hash(d);while(true){if(occupied_flag[h]==false){if(extend_rate(occupied+1)){extend();h=hash(d);continue;}data[h]=d;occupied_flag[h]=true;++occupied,++s;returnitr(h,this);}if(data_to_key(data[h])==data_to_key(d)){if(deleted_flag[h]==true){data[h]=d;deleted_flag[h]=false;++s;}returnitr(h,this);}h=(h+1)&(cap-1);}}// tips for speed up :// if return value is unnecessary, make argument_2 false.itrerase(itrit,boolget_next=true){if(it==this->end())returnthis->end();s--;if(!get_next){this->deleted_flag[it.i]=true;if(shrink_rate(s))shrink();returnthis->end();}itrnxt=it;nxt++;this->deleted_flag[it.i]=true;if(shrink_rate(s)){Datad=data[nxt.i];shrink();it=find(data_to_key(d));}returnnxt;}itrerase(constKey&key){returnerase(find(key));}intcount(constKey&key){returnfind(key)==end()?0:1;}boolempty()const{returns==0;}intsize()const{returns;}voidclear(){fill(std::begin(occupied_flag),std::end(occupied_flag),false);fill(std::begin(deleted_flag),std::end(deleted_flag),false);s=occupied=0;}voidreserve(intn){if(n<=0)return;n=1<<min(23,__lg(n)+2);if(cap<u32(n))reallocate(n);}};template<typenameKey,typenameData>uint64_tHashMapBase<Key,Data>::r=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();}// namespace HashMapImpl/**
* @brief Hash Map(base) (ハッシュマップ・基底クラス)
*/#line 4 "hashmap/hashmap.hpp"
template<typenameKey,typenameVal>structHashMap:HashMapImpl::HashMapBase<Key,pair<Key,Val>>{usingbase=typenameHashMapImpl::HashMapBase<Key,pair<Key,Val>>;usingHashMapImpl::HashMapBase<Key,pair<Key,Val>>::HashMapBase;usingData=pair<Key,Val>;Val&operator[](constKey&k){typenamebase::u32h=base::inner_hash(k);while(true){if(base::occupied_flag[h]==false){if(base::extend_rate(base::occupied+1)){base::extend();h=base::hash(k);continue;}base::data[h].first=k;base::data[h].second=Val();base::occupied_flag[h]=true;++base::occupied,++base::s;returnbase::data[h].second;}if(base::data[h].first==k){if(base::deleted_flag[h]==true){base::data[h].second=Val();base::deleted_flag[h]=false;++base::s;}returnbase::data[h].second;}h=(h+1)&(base::cap-1);}}typenamebase::itremplace(constKey&key,constVal&val){returnbase::insert(Data(key,val));}};/*
* @brief ハッシュマップ(連想配列)
* @docs docs/hashmap/hashmap.md
**/#line 2 "internal/internal-math.hpp"
#line 2 "internal/internal-type-traits.hpp"
#include<type_traits>usingnamespacestd;namespaceinternal{template<typenameT>usingis_broadly_integral=typenameconditional_t<is_integral_v<T>||is_same_v<T,__int128_t>||is_same_v<T,__uint128_t>,true_type,false_type>::type;template<typenameT>usingis_broadly_signed=typenameconditional_t<is_signed_v<T>||is_same_v<T,__int128_t>,true_type,false_type>::type;template<typenameT>usingis_broadly_unsigned=typenameconditional_t<is_unsigned_v<T>||is_same_v<T,__uint128_t>,true_type,false_type>::type;#define ENABLE_VALUE(x) \
template <typename T> \
constexpr bool x##_v = x<T>::value;
ENABLE_VALUE(is_broadly_integral);ENABLE_VALUE(is_broadly_signed);ENABLE_VALUE(is_broadly_unsigned);#undef ENABLE_VALUE
#define ENABLE_HAS_TYPE(var) \
template <class, class = void> \
struct has_##var : false_type {}; \
template <class T> \
struct has_##var<T, void_t<typename T::var>> : true_type {}; \
template <class T> \
constexpr auto has_##var##_v = has_##var<T>::value;
#define ENABLE_HAS_VAR(var) \
template <class, class = void> \
struct has_##var : false_type {}; \
template <class T> \
struct has_##var<T, void_t<decltype(T::var)>> : true_type {}; \
template <class T> \
constexpr auto has_##var##_v = has_##var<T>::value;
}// namespace internal#line 4 "internal/internal-math.hpp"
namespaceinternal{#include<cassert>
#include<utility>
#include<vector>usingnamespacestd;// a mod ptemplate<typenameT>Tsafe_mod(Ta,Tp){a%=p;ifconstexpr(is_broadly_signed_v<T>){if(a<0)a+=p;}returna;}// 返り値:pair(g, x)// s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/gtemplate<typenameT>pair<T,T>inv_gcd(Ta,Tp){static_assert(is_broadly_signed_v<T>);a=safe_mod(a,p);if(a==0)return{p,0};Tb=p,x=1,y=0;while(a!=0){Tq=b/a;swap(a,b%=a);swap(x,y-=q*x);}if(y<0)y+=p/b;return{b,y};}// 返り値 : a^{-1} mod p// gcd(a, p) != 1 が必要template<typenameT>Tinv(Ta,Tp){static_assert(is_broadly_signed_v<T>);a=safe_mod(a,p);Tb=p,x=1,y=0;while(a!=0){Tq=b/a;swap(a,b%=a);swap(x,y-=q*x);}assert(b==1);returny<0?y+p:y;}// T : 底の型// U : T*T がオーバーフローしない かつ 指数の型template<typenameT,typenameU>Tmodpow(Ta,Un,Tp){a=safe_mod(a,p);Tret=1%p;while(n!=0){if(n%2==1)ret=U(ret)*a%p;a=U(a)*a%p;n/=2;}returnret;}// 返り値 : pair(rem, mod)// 解なしのときは {0, 0} を返すtemplate<typenameT>pair<T,T>crt(constvector<T>&r,constvector<T>&m){static_assert(is_broadly_signed_v<T>);assert(r.size()==m.size());intn=int(r.size());Tr0=0,m0=1;for(inti=0;i<n;i++){assert(1<=m[i]);Tr1=safe_mod(r[i],m[i]),m1=m[i];if(m0<m1)swap(r0,r1),swap(m0,m1);if(m0%m1==0){if(r0%m1!=r1)return{0,0};continue;}auto[g,im]=inv_gcd(m0,m1);Tu1=m1/g;if((r1-r0)%g)return{0,0};Tx=(r1-r0)/g%u1*im%u1;r0+=x*m0;m0*=u1;if(r0<0)r0+=m0;}return{r0,m0};}}// namespace internal#line 5 "modulo/mod-log.hpp"
// a^x = b (mod p) である最小の非負整数 x を返すint64_tmod_log(int64_ta,int64_tb,int64_tp){if((a%=p)<0)a+=p;if((b%=p)<0)b+=p;int64_tf,g,r=1%p;for(f=0;(g=gcd(a,p))>1;++f){if(b%g)return(r==b)?f:-1;b/=g;p/=g;(r*=(a/g))%=p;}if(p==1)returnf;int64_tir=internal::inv(r,p);(b*=ir)%=p;int64_tk=0,ak=1;HashMap<int64_t,int64_t>baby;for(;k*k<p;++k){if(baby.find(ak)==baby.end())baby[ak]=k;(ak*=a)%=p;}int64_tiak=internal::inv(ak,p);for(int64_ti=0;i<k;++i){if(baby.find(b)!=baby.end())returnf+i*k+baby[b];(b*=iak)%=p;}return-1;}