乱搞+STL平衡树 序列
考虑两种情况:1,q=1;2,q>1;
- O(N)枚举一遍即可。
可以发现最长不会超过log。那么枚举起点的效率为N*logN?暴力可过?(其实这就是正解。。)只要枚举a[i]和a[i+1],算出最小公比。
这里设k=a[i]/a[i+1] (假设a[i]>a[i+1])k=p1^x1*p2^x2…..。求出g=gcd(x1,x2….);最小q=p1^(x1/g)*p2^(x2/g)…..。
其实,已知q<=1000,如果k满足条件,则k为q的某一次方,枚举暴力找即可。(真正的暴力可过)
但是题目中为要求是一个子序列,所以不能重复。搞个set即可。
代码蛮丑的。。。。
#pragma GCC optimize("O3")
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#include<cmath>
#define N 100005
#define ll long long
using namespace std;
int read()
{
int sum=0,f=1;char x=getchar();
while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}
return sum*f;
}
inline ll check(ll k)
{
ll s=sqrt(k);
for(ll i=2;i<=s&&i<=1000;i++)
if(k%i==0)
{
ll j=k;
while(j%i==0)j/=i;
if(j==1)return i;
}
if(k<=1000)return k;
return 0;
}
int n;ll a[N];
int main()
{
//freopen("seq19.in","r",stdin);
//freopen("hh.txt","w",stdout);
n=read();
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
int ans=2;
for(int i=2,l=1;i<=n;i++)
{
if(a[i]==a[i-1])l++;
else{ans=max(l,ans);l=1;}
if(i==n)ans=max(ans,l);
}
set<ll> st;
for(int i=1;i<n;i++)
{
ll x=a[i],y=a[i+1],k;
if(x<y)swap(x,y);
if(x%y||x==y)continue;
k=x/y;k=check(k);
if(k==0)continue;
while(x%k==0)x/=k;
while(y%k==0)y/=k;
if(x!=y)continue;
st.clear();st.insert(a[i]);st.insert(a[i+1]);
for(int j=i+2;j<=n;j++)
{
if(st.count(a[j]))
{
if(ans<j-i)ans=j-i;
break;
}
if(a[j]%x)
{
if(ans<j-i)ans=j-i;
break;
}
ll g=a[j];g/=x;
while(g%k==0)g/=k;
if(g!=1)
{
if(ans<j-i)ans=j-i;
break;
}
st.insert(a[j]);
}
}
cout<<ans;
}