2019ICPC EC-FINAL H-King 随机

2019ICPC EC-FINAL H-King

题意

给一个长度为\(n\)的数组\(b\),从中找到一个长度大于等于\(\lceil \frac{n}{2} \rceil\)的子序列\(a\),存在一个\(q\)使得\(a\)中任意的下标\(i\)满足\(a_{i-1}*q \equiv a_i (mod~p)\)

\(n\le 2\cdot 10^5,p \le 10^9+7\)

分析

\(n\)个数中选出\(\frac{n}{2}\)个数,两个相邻的数的在原数组中最小距离最大为2,并且会有很多相邻的数的距离小于等于2,所以我们从\(1\sim n\)中随机一个数\(x\),枚举\(x+1,x+2\)作为和它相邻的数,计算出\(q\),然后前后各贪心扫一下,找到最长的等比数列,取最大值,最后和\(\lceil \frac{n}{2} \rceil\)比较一下即可。

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;++i)
#define per(i,n,a) for (int i=n;i>=a;--i)
#define sz(x) ((int)(x).size())
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
typedef pair<int,int> pii;
#define ll long long
const int inf=1e9;
const int mod=1e9+7;
const int N=2e5+10;
int T;
int n,p;
int b[N];
bool vis[N];
std::mt19937 rnd(time(0));
int ksm(int a,int b,int mod){
	int ret=1;
	while(b){
		if(b&1) ret=1ll*ret*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}
	return ret;
}
int solve(int x,int y){
	int q=1ll*b[y]*ksm(b[x],p-2,p)%p;
	int pre=1ll*b[y]*q%p;
	int ans=2;
	for(int i=y+1;i<=n;i++){
		if(b[i]==pre){
			++ans;
			pre=1ll*b[i]*q%p;
		}
	}
	q=ksm(q,p-2,p);
	int last=1ll*b[x]*q%p;
	for(int i=x-1;i>=1;i--){
		if(b[i]==last){
			++ans;
			last=1ll*b[i]*q%p;
		}
	}
	return ans;
}
int main(){
	//ios::sync_with_stdio(false);
	//freopen("in","r",stdin);
	scanf("%d",&T);
	while(T--){
		memset(vis,0,sizeof(vis));
		scanf("%d%d",&n,&p);
		rep(i,1,n){
			scanf("%d",&b[i]);
		}
		int ans=2;
		for(int i=1;i<=min(n,200);i++){
			int x=rnd()%n+1;
			while(vis[x]){
				x=rnd()%n+1;
			}
			vis[x]=1;
			for(int j=x+1;j<=n&&j<=x+2;j++) ans=max(ans,solve(x,j));
		}
		if(ans>=(n+1)/2) printf("%d\n",ans);
		else puts("-1");
	}
	return 0;
}
posted @ 2020-10-06 21:06  xyq0220  阅读(260)  评论(0编辑  收藏  举报