JZOJ 3895. 数字对
题目
分析
30% :暴力枚举判断。O(n^4)。 60% :特殊区间的特点实际上就是区间最小值等于这个区间的 GCD,于是暴力或递推算 出每个区间的最小值与 GCD。而对于最大价值,可以通过二分来进行求解。复杂 度 O(n ^ 2)。 100%:在 60%的基础上,最小值与 GCD 都使用 RMQ 算法来求解,对于这道题推荐使用 ST 表。最大价值仍然使用二分。复杂度 O(nlogn)。
- 但是我是暴力过
- 枚举节点k,向前找,向后找最大公约数
- 加个快读就过了
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define M 500010 6 using namespace std; 7 long long n,a[M],mxx,mxl,sum,Ans[M]; 8 struct sb{ 9 int len,l; 10 }ans[M]; 11 long long init(){ 12 13 int x=0;char s=getchar(); 14 while(s<'0'||s>'9')s=getchar(); 15 while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 16 return x; 17 } 18 bool cmp(sb x,sb y){ 19 if(x.len==y.len) return x.l<y.l; 20 return x.len>y.len; 21 } 22 long long Gcd(long long a,long long b){ 23 if (b==0) 24 { 25 return a; 26 } 27 Gcd(b,a%b); 28 } 29 int main() 30 { 31 n=init(); 32 for(int i=1;i<=n;i++) 33 a[i]=init(); 34 for(int k=1;k<=n;k++) 35 { 36 int li=k,ri=k,gcd=a[k]; 37 for(int i=k+1;i<=n;i++) 38 { 39 if(Gcd(gcd,a[i])!=gcd) 40 break; 41 else ri++; 42 } 43 for(int i=k-1;i>=1;i--) 44 { 45 if(Gcd(gcd,a[i])!=gcd) 46 break; 47 else li--; 48 } 49 50 ans[k].len=ri-li; 51 ans[k].l=li; 52 } 53 sort(ans+1,ans+1+n,cmp); 54 mxx=ans[1].len;mxl=ans[1].l; 55 Ans[++sum]=mxl; 56 for(int k=2;k<=n;k++) 57 if(ans[k].len!=mxx) 58 break; 59 else if(ans[k].l!=mxl) 60 { 61 Ans[++sum]=ans[k].l; 62 mxl=ans[k].l; 63 } 64 cout<<sum<<" "<<mxx<<endl; 65 for(int i=1;i<=sum;i++) 66 cout<<Ans[i]<<" "; 67 return 0; 68 }
为何要逼自己长大,去闯不该闯的荒唐