传送门
hash。
暴力枚举k,然后每次hash。
朴素的求法时间会爆,那么转化成前缀和乱搞。
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll unsigned long long
const int max_n=3e5+5;
const int Mod=1e9+7;
int n,S;
int a[max_n];
ll s1[max_n],s2[max_n];
ll mi[max_n];
int ans,ansk,ANS[max_n];
map bool > hash;
inline void Do_It(int k){
int tot=0;
hash.clear();
for (int i=1;i<=n-k+1;i+=k){
if ((n/k)-(i/k)+totbreak;
ll ans1=s1[i+k-1]-s1[i-1]*mi[k];
ll ans2=s2[i]-s2[i+k]*mi[k];
ll major=ans1*ans2;
if (hash[major])
continue;
else{
tot++;
hash[major]=true;
}
}
if (tot>ans){
ans=tot;
ansk=1;
ANS[ansk]=k;
}
else if (tot==ans)
ANS[++ansk]=k;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
S=n+1;
mi[0]=1;
for (int i=1;i<=n;++i)
mi[i]=mi[i-1]*S;
for (int i=1;i<=n;++i)
s1[i]=s1[i-1]*S+a[i];
for (int i=n;i>=1;--i)
s2[i]=s2[i+1]*S+a[i];
for (int i=1;i<=n;++i){
if (ans*i>n) break;
Do_It(i);
}
printf("%d %d\n",ans,ansk);
for (int i=1;i<=ansk;++i)
printf("%d%c",ANS[i]," \n"[i==ansk]);
}
学会了基本的东西像这些简单的转化能想到才行啊!