【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 lct1999,我WA了的原因:
1.每组数据还是需要清一下tot数组的,不能光靠加新点的时候清tot[i&1],第一个点应该把tot[0]也清掉。
2.每次是更新这一段的gcd,所以是要记录gcd的,不能光记个端点,每次求两个端点的gcd……这明显不对啊好吗= =
蒟蒻果然好弱啊……退OI保平安吧QAQ
1 /************************************************************** 2 Problem: 4052 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:820 ms 7 Memory:5180 kb 8 ****************************************************************/ 9 10 //BZOJ 4052 11 #include<vector> 12 #include<cstdio> 13 #include<cstdlib> 14 #include<cstring> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 using namespace std; 21 typedef long long LL; 22 LL getLL(){ 23 LL v=0,sign=1; char ch=getchar(); 24 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 25 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 26 return v*sign; 27 } 28 const int N=100010,INF=~0u>>2; 29 /*******************template********************/ 30 LL a[N],f[2][N],b[2][N],n; 31 int tot[2]; 32 inline LL gcd(LL a,LL b){return b?gcd(b,a%b):a;} 33 34 int main(){ 35 #ifndef ONLINE_JUDGE 36 freopen("input.txt","r",stdin); 37 // freopen("output.txt","w",stdout); 38 #endif 39 int T=getLL(),now; 40 while(T--){ 41 n=getLL(); 42 tot[0]=tot[1]=0; 43 LL ans=0; 44 F(i,1,n){ 45 now=i&1; 46 tot[now]=0; 47 a[i]=getLL(); 48 F(j,1,tot[now^1]){ 49 int k=b[now^1][j]; 50 if ( j>1 && gcd(a[i],f[now^1][j])==gcd(a[i],f[now^1][j-1]) ) continue; 51 b[now][++tot[now]]=b[now^1][j]; 52 f[now][tot[now]]=gcd(a[i],f[now^1][j]); 53 ans=max(ans,f[now][tot[now]]*(i-k+1)); 54 } 55 if (f[now][tot[now]]!=a[i]){ 56 b[now][++tot[now]]=i; 57 f[now][tot[now]]=a[i]; 58 } 59 // F(j,1,tot[now]) printf("%lld ",b[now][j]); puts(""); 60 // F(j,1,tot[now]) printf("%lld ",f[now][j]); puts(""); 61 ans=max(ans,a[i]); 62 } 63 printf("%lld\n",ans); 64 } 65 return 0; 66 }
4052: [Cerc2013]Magical GCD
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 146 Solved: 68
[Submit][Status][Discuss]
Description
给出一个长度在 100 000 以内的正整数序列,大小不超过 10^12。
求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大。
Input
Output
Sample Input
1
5
30 60 20 20 20
5
30 60 20 20 20
Sample Output
80