今天上课讲的题。


做法就直接枚举约数,或者说分解质因数。后者可以预处理到log。


判循环也比较开心。直接用一些奇奇怪怪的字符串的性质就好了。


看来字符串很博大精深啊。


#include <cstdio>

#include <cctype>

#include <cstring>

#include <algorithm>


using namespace std;


typedef unsigned long long qw;

typedef pair <int, qw> hstrv;


#define _l (long long int)


int _d_;

#define readInt(_x_) { \

int& _s_ = _x_; \

while (!isdigit(_d_ = getchar())); \

_s_ = 0; \

while ((_s_ = _s_ * 10 + _d_ - 48), isdigit(_d_ = getchar())); \

}


const int maxn = 500009;

const int base = 257;

const int hmod = 1000000093;


int pba[maxn];

qw pbb[maxn];


struct hstr {

int a[maxn];

qw b[maxn];

int init(char* x) {

a[0] = 0;

b[0] = 0;

int n = 1;

for (++ x; *x; ++ x, ++ n) {

a[n] = (_l a[n - 1] * base + *x) % hmod;

b[n] = b[n - 1] * base + *x;

}

return n - 1;

}

inline hstrv range(int l, int r) {

int x = ((a[r] - _l a[l - 1] * pba[r - l + 1]) % hmod + hmod) % hmod;

qw y = b[r] - b[l - 1] * pbb[r - l + 1];

return hstrv(x, y);

}

};


char a[maxn];

hstr ha;

int n, q;

int pn[maxn], tp, mf[maxn];

bool pr[maxn];


void pre() {

pba[0] = 1;

pbb[0] = 1;

for (int i = 1; i < maxn; ++ i) {

pba[i] = _l pba[i - 1] * base % hmod;

pbb[i] = pbb[i - 1] * base;

}

memset(pn, 0, sizeof(pn));

tp = 0;

for (int i = 2; i <= n; ++ i) {

if (!pr[i]) {

pn[tp ++] = i;

mf[i] = i;

}

for (int j = 0; j < tp && i * pn[j] <= n; ++ j) {

pr[i * pn[j]] = 1;

mf[i * pn[j]] = pn[j];

if (i % pn[j] == 0)

break;

}

}

}


int main() {

#ifndef ONLINE_JUDGE

freopen("in.txt", "r", stdin);

#endif


readInt(n);

pre();

scanf("%s", a + 1);

ha. init(a);

readInt(q);

while (q --) {

int l, r, s;

readInt(l);

readInt(r);

s = r - l + 1;

for (int i = s, j; i > 1; i /= mf[i]) {

j = s / mf[i];

if (ha. range(l, r - j) == ha. range(l + j, r))

s = j;

}

printf("%d\n", s);

}

}