bzoj 4052: [Cerc2013]Magical GCD

bzoj4488的双倍经验!!

 1 #include <bits/stdc++.h>
 2 #define LL long long
 3 using namespace std;
 4 inline LL ra()
 5 {
 6     LL x=0; char ch=getchar();
 7     while (ch<‘0‘ || ch>‘9‘) ch=getchar();
 8     while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();}
 9     return x;
10 }
11
12 const int maxn=100005;
13
14 struct node{
15     LL num; int x;
16     bool operator < (const node &y) const {return num<y.num||num==y.num && x<y.x;}
17 }f[2][maxn];
18 LL a[maxn];
19 int n;
20
21 LL gcd(LL x, LL y) {return y==0?x:gcd(y,x%y);}
22
23 int main()
24 {
25     int T=ra();
26     while (T--)
27     {
28         n=ra();
29         for (int i=1; i<=n; i++) a[i]=ra();
30         int s1=0,s2=0;
31         int p=0,q=1;
32         LL ans=0; node d;
33         for (int i=1; i<=n; i++)
34         {
35             for (int j=1; j<=s1; j++) f[p][j].num=gcd(a[i],f[p][j].num);
36             d.num=a[i]; d.x=i; s1++; f[p][s1]=d;
37             sort(f[p]+1,f[p]+s1+1);
38             s2=0;
39             for (int j=1; j<=s1; j++)
40                 if (f[p][j].num!=f[p][j-1].num)
41                     f[q][++s2]=f[p][j];
42             for (int j=1; j<=s2; j++) ans=max(ans,f[q][j].num*(LL)(i-f[q][j].x+1));
43             p^=1; q^=1; s1=s2;
44         }
45         printf("%lld\n",ans);
46     }
47     return 0;
48 }
时间: 2024-10-07 05:29:51

bzoj 4052: [Cerc2013]Magical GCD的相关文章

4052: [Cerc2013]Magical GCD

4052: [Cerc2013]Magical GCD Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 148  Solved: 70[Submit][Status][Discuss] Description 给出一个长度在 100 000 以内的正整数序列,大小不超过 10^12. 求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大. Input Output Sample Input 1 5 30 60 20 20 2

【BZOJ4052】[Cerc2013]Magical GCD 乱搞

[BZOJ4052][Cerc2013]Magical GCD Description 给出一个长度在 100 000 以内的正整数序列,大小不超过 10^12. 求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大. Sample Input 1 5 30 60 20 20 20 Sample Output 80 题解:先思考暴力的做法.我们从一个数开始往左扫,将所有使得gcd改变的位置都记录下来.由于gcd的每次改变都至少/2,所以这样的位置不超过log个. 那么我们

[Cerc2013]Magical GCD

https://vjudge.net/problem/UVA-1642 题意:在一个序列中,找出一段连续的序列,使得长度*gcd最大 固定右端点,当左端点从左向右移动时,gcd不变或变大 gcd相同时,序列越长越好 所以相同的gcd只记录最靠左的位置 当右端点由r转移向r+1时 重新计算gcd,然后去重 gcd最多只会有log个 #include<cstdio> #include<iostream> #include<algorithm> #define N 10000

[BZOJ4052][Cerc2013]Magical GCD

试题描述 给出一个长度在 100 000 以内的正整数序列,大小不超过 10^12. 求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大. 输入 本题为多组数据. 第一行一个整数 T,表示数据组数. 每组数据第一行为一个整数 n,表示序列长度:第二行为 n 个整数表示序列. 输出 对于每组数据,输出 max{ gcd * length } 输入示例 1 5 30 60 20 20 20 输出示例 80 数据规模及约定 见"试题描述" 题解 可以发现,随着子序列

【数论】【暴力】bzoj4052 [Cerc2013]Magical GCD

考虑向一个集合里添加一个数,它们的gcd要么不变,要么变成原gcd的一个约数.因此不同的gcd只有log个. 所以对于每个位置,维护一个表,存储从这个位置向前所有的不同的gcd及其初始位置,然后暴力更新答案,反正这个表不会很长. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define N 100001 typedef long long ll; typedef

【bzoj4052】[Cerc2013]Magical GCD 暴力

题目描述 给出一个长度在 100 000 以内的正整数序列,大小不超过 10^12. 求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大. 样例输入 1 5 30 60 20 20 20 样例输出 80 题解 暴力 由于$\gcd$具有结合律,所以如果$\gcd(a,b)$比$a$小,那么至少小了一半. 所以所有以一个数为右端点的区间中,本质不同的$\gcd$个数只有$\log a$个. 于是从左向右枚举右端点,统计出以该点为右端点的所有$\gcd$以及区间长度,统计答

【BZOJ】【4052】【CERC2013】Magical GCD

DP/GCD 然而蒟蒻并不会做…… Orz @lct1999神犇 首先我们肯定是要枚举下端点的……嗯就枚举右端点吧…… 那么对于不同的GCD,对应的左端点最多有log(a[i])个:因为每次gcd缩小,至少变成gcd/2(2是最小的质因数),所以是log个左端点…… 所以我们就有了log段!每段的gcd是相同的.当我们加入一个新的右端点时,除了该节点本身外,不会出现新的左端点,原有的左端点可能会不变,或是两(多)段合并成一段,用滚动数组记一下,暴力搞就可以了……$O(n*log^2n)$ Orz

UVA 1642 Magical GCD 暴力+簡單數論

枚舉右端點,往前查找左端點.... 右端點一定的話,最多只有log個不同的gcd值, 用一個數組記錄不同的GCD的值,對每個相同的GCD值記錄一下最靠左的位置... 因爲GCD值不是很多所以 移動右端點時暴力統計即可.. 對與樣例: 30 60 20 20 20 從第1個數座右端點開始枚舉  // (gcd,位置) (30,1) 枚舉以第2個數做爲右端點 (30,1) (60,2) 第3個數 (10,1)  (20,2) .... 後面幾個數都是一樣的... 第5個數 (10,1)  (20,2

【NOIP2014模拟8.17】Magical GCD

题目 对于一个由正整数组成的序列, Magical GCD 是指一个区间的长度乘以该区间内所有数字的最大公约数.给你一个序列,求出这个序列最大的 Magical GCD. 分析 根据暴力的思想, \(枚举i,枚举j,a[j]=gcd(a[j],a[i])\) 答案就是\(max(a[j]*(i-j+1))\) 显然,当\(a[j]=a[j-1]\)的时候,\(a[j]\)就一定不会更新ans,所以,弄个双向链表,把\(a[j]\)踢掉. #include <cmath> #include &l