#pragma once
structRollingHashBase{usingu128=__uint128_t;usingi128=__int128_t;usingu64=uint64_t;staticconstexpru64MOD=(1ull<<61)-1;staticu64base;staticu64add(u64x,u64y){if((x+=y)>=MOD)x-=MOD;returnx;}staticu64sub(u64x,u64y){if((x-=y)>=MOD)x+=MOD;returnx;}staticu64mul(u64x,u64y){u128z=(u128)x*y;u64v=(u64(z)&MOD)+u64(z>>61);returnv>=MOD?v-MOD:v;}staticu64normalize(u64v){u64x=(v&MOD)+(v>>61);returnx>=MOD?x-MOD:x;}template<classT>staticu64normalize(Tv){static_assert(is_integral_v<T>&&sizeof(T)<=sizeof(u64));ifconstexpr(is_signed_v<T>){if(v<0){u64x=normalize(u64(-i128(v)));returnx==0?0:MOD-x;}}returnnormalize(u64(v));}template<classT>staticTrestore(u64v){static_assert(is_integral_v<T>&&sizeof(T)<=sizeof(u64));assert(v<MOD);ifconstexpr(is_signed_v<T>){if(v<=u64(numeric_limits<T>::max()))returnT(v);u64x=MOD-v;assert(i128(x)<=-i128(numeric_limits<T>::min()));returnT(-i128(x));}else{assert(v<=u64(numeric_limits<T>::max()));returnT(v);}}};inlineRollingHashBase::u64RollingHashBase::base=[](){random_deviceseed_gen;mt19937_64rnd(seed_gen());returnuniform_int_distribution<u64>(256,MOD-2)(rnd);}();