King Gym - 102471H
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)
qai−1≡ai(modp)
题解:
q
a
i
−
1
≡
a
i
(
m
o
d
p
)
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
−
(
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 K. King's Rout(topo排序+逆向思维)
CF gym 101933 K King's Colors —— 二项式反演