King Gym - 102471H

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了King Gym - 102471H相关的知识,希望对你有一定的参考价值。

King Gym - 102471H

题意:

给你一个数组b,让你找到一个最长的最长的king子序列,如果长度大于等于n/2,输出长度值,否则输出-1
一个序列 ( a 1 , a 2 , . . . , a n ) (a_{1},a_{2},...,a_{n}) (a1,a2,...,an)是king序列当且仅当存在一个整数q,1<=q<p,对于所有的i∈[2,n], q a i − 1 ≡ a i ( m o d    p ) qa_{i-1}≡a_{i}(\\mod p) qai1ai(modp)

题解:

q a i − 1 ≡ a i ( m o d    p ) qa_{i-1}≡a_{i}(\\mod p) qai1ai(modp)这个式子可以理解为在模p意义下找到一个最长的等比数列,q是多少不知道
题目有个特殊性质,如果长度大于等于n/2,输出长度值,小于输出-1。当答案超过n/2时,说明有一半以上的数都参与了king子序列的组成,也就说说子序列中相邻两个数在原序列中不会距离太远,一定会有两个数相邻或者紧靠着
我们随机在序列最终随机取两个数,这两个数出现在序列中的可能性大于1/4((1/2) * (1/2) = (1/4) )
如果我们取x次,出现在答案的可能性就变成 1 − ( 3 4 ) x 1-(\\frac{3}{4})^x 1(43)x
只要x够大,可能性就无限趋近于1
因此这个题可以这样搞,我们每次随机一个位置x,分别选取(x,x+1)或者(x,x+1)作为king子序列中的一部分,然后求公比,求最长子序列的长度,一直更新最大长度即可

代码:

#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{
    x= 0;
    char c= getchar();
    bool flag= 0;
    while (c < '0' || c > '9')
        flag|= (c == '-'), c= getchar();
    while (c >= '0' && c <= '9')
        x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();
    if (flag)
        x= -x;
    read(Ar...);
}
template <typename T> inline void write(T x)
{
    if (x < 0) {
        x= ~(x - 1);
        putchar('-');
    }
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#else
    startTime = clock ();
    freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#else
    endTime= clock();
    printf("\\nRun Time:%lfs\\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
mt19937 rnd(time(0));
int n;
ll p;
ll poww(ll a,ll b){
	ll ans=1;
	while(b){
		if(b&1)ans=ans*a%p;
		a=a*a%p;
		b>>=1;
	}
	return ans%p;
}
const int maxn=2e5+9;
ll dp[maxn];
ll a[maxn];

unordered_map<ll,ll>mp;
ll solve(int l,int r){
	ll res=0;
	ll q,inv;//概率
	q=1ll*a[r]*poww(a[l],p-2)%p;
//	cout<<"q="<<q<<endl;
	inv=poww(q,p-2);
	
	for(int i=1;i<=n;i++){
		ll pre=1ll*a[i]*inv%p;
		if(mp.count(pre))dp[i]=mp[pre]+1;
		else dp[i]=1;
		
		mp[a[i]]=max(mp[a[i]],dp[i]);
		res=max(res,dp[i]);
	}
	mp.clear();
	return res;
}
int main()
{
    //rd_test();
	int t;
	read(t);
	while(t--){
		
		scanf("%d%lld",&n,&p);
		for(int i=1;i<=n;i++)read(a[i]);
		ll ans=0;
		for(int i=1;i<=25;i++){
			int x=rnd()%(n-1)+1;
//			printf("%d %d\\n",x,x+1);
			if(x+1<=n)ans=max(ans,solve(x,x+1));
			if(x+2<=n)ans=max(ans,solve(x,x+2)); 
		}
		if(ans*2<n)printf("-1\\n");
		else printf("%lld\\n",ans);
	}
    //Time_test();
}




以上是关于King Gym - 102471H的主要内容,如果未能解决你的问题,请参考以下文章

Gym 100792 King's Rout 拓扑排序

Gym 101933 King's Colors

GYM 100792 K. King's Rout(topo排序+逆向思维)

CF gym 101933 K King's Colors —— 二项式反演

CF gym 101933 K. King's Colors(二项式反演)

Gym - 101670C Chessboard Dancing(找规律)