題目傳送門:http://www.lydsy.com/JudgeOnline/problem.php?id=2795
思路:這其實是一道傻逼題,但數據範圍略大了,根本是在欺騙我的感情。
考慮循環節是什麼?循環節就是連續重複的子串,設總長度爲
考慮從質因數分解的角度優化它,設
時間複雜度:
經打表可以得知
代碼:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#define N 500000
using namespace std;
typedef unsigned long long LL;
LL bin[N + 5],hash[N + 5];
LL n,cnt,prime[N + 5],num[N + 5],f[2][10][N + 5],p,q;
bool not_prime[N + 5];
char s[N + 5];
inline void get_prime(){
memset(not_prime,0,sizeof(not_prime));
cnt = 0;
for (LL i = 2;i <= n; ++i){
if (!not_prime[i]) prime[++cnt] = i;
for (LL j = 1;j <= cnt; ++j)
if (i * prime[j] > n) break;
else {
not_prime[i * prime[j]] = 1;
if (!(i % prime[j])) break;
}
}
}
inline void init(){
scanf("%llu",&n);
scanf("%s",s + 1);
get_prime();
memset(f,0,sizeof(f));
memset(num,0,sizeof(num));
for (LL i = 1;i <= cnt; ++i)
for (LL j = prime[i];j <= n; j += prime[i]){
num[j]++; f[0][num[j]][j] = prime[i];
LL x = j;
while (!(x % prime[i])) { f[1][num[j]][j]++; x /= prime[i]; }
}
p = 37;
bin[0] = 1;
for (LL i = 1;i <= n; ++i) bin[i] = bin[i - 1] * p;
hash[0] = 0;
for (LL i = 1;i <= n; ++i) hash[i] = hash[i - 1] + bin[i - 1] * (s[i] - 96LL);
}
inline LL check(LL ss,LL ll,LL cir){
for (LL i = ss + cir;i < ss + ll;i += cir)
if (!(((hash[i - 1] - hash[i - cir - 1]) * bin[cir]) == (hash[i + cir - 1] - hash[i - 1])))
return 0;
return 1;
}
inline LL get_ans(LL a,LL b){
LL l = b - a + 1,ans;
ans = l;
for (LL i = 1;i <= num[l]; ++i){
for (LL j = f[1][i][l];j; --j)
if (!check(a,ans,ans / f[0][i][l])) break;
else ans /= f[0][i][l];
}
return ans;
}
inline void DO_IT(){
LL Q,a,b;
scanf("%llu",&Q);
while (Q--){
scanf("%llu%llu",&a,&b);
printf("%llu\n",get_ans(a,b));
}
}
int main(){
init();
DO_IT();
return 0;
}
總結:1.當問題不容易做時可以想各種小優化
2.從質因數分解的角度考慮問題
3.相比較自然溢出跑得飛快