King Gym - 102471H
题意:
给你一个数组b,让你找到一个最长的最长的king子序列,如果长度大于等于n/2,输出长度值,否则输出-1
一个序列(a1,a2,...,an)(a_{1},a_{2},...,a_{n})(a1,a2,...,an)是king序列当且仅当存在一个整数q,1<=q<p,对于所有的i∈[2,n],qai−1≡ai(modp)qa_{i-1}≡a_{i}(\mod p)qai−1≡ai(modp)
题解:
qai−1≡ai(modp)qa_{i-1}≡a_{i}(\mod p)qai−1≡ai(modp)这个式子可以理解为在模p意义下找到一个最长的等比数列,q是多少不知道
题目有个特殊性质,如果长度大于等于n/2,输出长度值,小于输出-1。当答案超过n/2时,说明有一半以上的数都参与了king子序列的组成,也就说说子序列中相邻两个数在原序列中不会距离太远,一定会有两个数相邻或者紧靠着
我们随机在序列最终随机取两个数,这两个数出现在序列中的可能性大于1/4((1/2) * (1/2) = (1/4) )
如果我们取x次,出现在答案的可能性就变成1−(34)x1-(\frac{3}{4})^x1−(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
#elsestartTime = clock ();freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#elseendTime= 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();
}