
題意:就是找個(gè)連續(xù)子序列,使得長(zhǎng)度乘上這個(gè)子序列的gcd的值最大。
思路:嗯,比較容易想到的就是暴力,每次就是和前一個(gè)、前兩個(gè).....求gcd乘上長(zhǎng)度。
好想的一個(gè)優(yōu)化就是gcd相同的,我們只保留最長(zhǎng)的那個(gè)序列就可以了。
我們保存[i,j-1]的gcd的數(shù)值。以及i這個(gè)位置
然后和j去求一個(gè)gcd。如果gcd沒(méi)變。那么這個(gè)序列的值不變,最左邊還是i,gcd也不變。
如果gcd變小了,那么當(dāng)前這個(gè)序列就要改變,gcd的值改變,i的位置取之前最靠前的一個(gè)值。
這樣我們每次保存一個(gè)最小的i就可以了。
很重要的一點(diǎn)就是隨著數(shù)量的增加gcd是不斷減小的。
然后不斷的更新答案就可以了。
#include <bits/stdc++.h>using namespace std;typedef long long ll;ll a[100005];map<ll,ll>v;map<ll,ll>::iterator it,itt;ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}int main(){ int T,n; scanf("%d",&T); while (T--) { ll ans=0; scanf("%d",&n); v.clear(); for (int i=1; i<=n; i++) { scanf("%lld",&a[i]); ans=max(ans,a[i]); for (it=v.begin(); it!=v.end(); it++) { if(gcd(it->first,a[i])!=it->first)//gcd的值變小了 { if (!v[gcd(it->first,a[i])])//如果之前沒(méi)出現(xiàn)過(guò) v[gcd(it->first,a[i])]=it->second; cout<<v.size()<<endl; //刪除當(dāng)前的值 itt=it++; v.erase(itt); it--; } } if (!v[a[i]])v[a[i]]=i; cout<<v.size()<<endl; for (auto it:v) { ans=max(ans,(it.first)*(i-it.second+1)); } } PRintf("%lld/n",ans); } return 0;}
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注