King Gym - 102471H
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(); }總結
以上是生活随笔為你收集整理的King Gym - 102471H的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 说话经常结巴是为什么?
- 下一篇: 喉咙痛眼睛涨怎么回事?