#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define popcount __builtin_popcount using namespace std; typedef long long int ll; typedef pair P; //https://judge.yosupo.jp/submission/877 #define MP make_pair #define fi first #define se second #define ALL(a) (a).begin(),(a).end() struct SuffixArray{ ll size; string s; vectordata; SuffixArray(string S):size(S.size()),s(S){ s += '$'; vectorinput(s.size()); for(ll i=0;i induced_sort(vectort, ll kind){ ll sz = t.size(); vectorls(sz);//trueはL型,falseはS型 for(ll i = sz-1;i>=0;i--){ if(i==sz-1)ls[i] = false; else{ if(t[i]!=t[i+1])ls[i] = (t[i] > t[i+1]); else ls[i] = ls[i+1]; } } vectorcnt(kind); for(ll i=0;ilr(kind,MP(-1,-1)); for(ll i=1;ilmsidx,ret(sz,-1); for(ll i=0;i=1&&ls[ret[i]-1]){ ret[lr[t[ret[i]-1]].fi+cnt[t[ret[i]-1]]]=ret[i]-1; cnt[t[ret[i]-1]]++; if(i!=0&&!ls[ret[i]])ret[i]=-1; } } fill(ALL(cnt),0); for(ll i=sz-1;i>=1;i--){ if(ret[i]>=1&&!ls[ret[i]-1]){ ret[lr[t[ret[i]-1]].se-cnt[t[ret[i]-1]]]=ret[i]-1; cnt[t[ret[i]-1]]++; } } vectorrev_lmsidx(sz,-1),lmsinput(lmsidx.size(),-1); for(ll i=0;icomp(t.begin()+ret[0],t.end()); for(ll i=1;i=1&&ls[ret[i]-1]&&!ls[ret[i]]){ vectortmp(t.begin()+ret[i],t.begin()+lmsidx[rev_lmsidx[ret[i]]+1]+1); if(comp != tmp){ kindnum++; comp = tmp; } lmsinput[rev_lmsidx[ret[i]]] = kindnum; } } vectoroutput; if(kindnum==lmsidx.size()){ output.assign(kindnum,-1); for(ll i=0;i=0;i--){ ll tmp=lmsidx[output[i]]; ret[lr[t[tmp]].se - cnt[t[tmp]]]=tmp; cnt[t[tmp]]++; } fill(ALL(cnt),0); for(ll i=0;i=1&&ls[ret[i]-1]){ ret[lr[t[ret[i]-1]].fi+cnt[t[ret[i]-1]]]=ret[i]-1; cnt[t[ret[i]-1]]++; if(i!=0&&!ls[ret[i]])ret[i]=-1; } } fill(ALL(cnt),0); for(ll i=sz-1;i>=1;i--){ if(ret[i]>=1&&!ls[ret[i]-1]){ ret[lr[t[ret[i]-1]].se-cnt[t[ret[i]-1]]]=ret[i]-1; cnt[t[ret[i]-1]]++; } } return ret; } ll operator[](const int &k) const{ return data[k]; } }; struct LCP{ SuffixArray sa; vector lcp, rk; LCP(SuffixArray sa):sa(sa), lcp(sa.size), rk(sa.size+1){ rk[sa.size]=0; for(int i=0; i0) h--; for(; j+h struct SegmentTree{ using F=function; int sz; vector seg; const F f; const Monoid e; SegmentTree(int n, const F f, const Monoid &e): f(f), e(e){ sz=1; while(sz v): f(f), e(e){ sz=1; while(sz=1; i--){ seg[i]=f(seg[2*i], seg[2*i+1]); } } void update(int k, const Monoid &x){ k+=sz; seg[k]=x; while(k>1){ k>>=1; seg[k]=f(seg[2*k], seg[2*k+1]); } } Monoid query(int a, int b){ a+=sz, b+=sz; Monoid ret=e; for(;a>=1, b>>=1){ if(b&1) ret=f(ret, seg[--b]); if(a&1) ret=f(ret, seg[a++]); } return ret; } Monoid operator[](const int &k) const{ return seg[k+sz]; } }; int main() { int n; cin>>n; string s; int id[100010], len[100010]; for(int i=0; i>si; s+=si; len[i]=si.size(); id[i+1]=id[i]+len[i]; } SuffixArray sa(s); LCP lcp(sa); vector v(s.size()); for(int i=0; i seg(s.size(), [](int a, int b){ return min(a, b);}, INF, v); int m; ll x, d; cin>>m>>x>>d; ll ans=0; for(int i=0; iq) swap(p, q); else q++; int ml=min(len[p], len[q]); bool ok=0; for(int j=0; j<20; j++){ if(j==ml){ ok=1; ans+=ml; break; } if(s[id[p]+j]!=s[id[q]+j]){ ok=1; ans+=j; break; } } x=(x+d)%((ll)n*(n-1)); if(ok) continue; int p1=lcp.rk[id[p]], q1=lcp.rk[id[q]]; if(p1>q1) swap(p1, q1); ans+=min(ml, seg.query(p1, q1)); } cout<