Bzoj4488 [Jsoi2015]最大公约数
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 172 Solved: 101
Description
给定一个长度为 N 的正整数序列Ai对于其任意一个连续的子序列
{Al,Al+1...Ar},我们定义其权值W(L,R )为其长度与序列中所有元素的最大公约数的乘积,即W(L,R) = (R-L+1) ∗ gcd (Al..Ar)。
JYY 希望找出权值最大的子序列。
Input
输入一行包含一个正整数 N。
接下来一行,包含 N个正整数,表示序列Ai
1 < = Ai < = 10^12, 1 < = N < = 100,000
Output
输出文件包含一行一个正整数,表示权值最大的子序列的权值。
Sample Input
5
30 60 20 20 20
30 60 20 20 20
Sample Output
80
//最佳子序列为最后 4 个元素组成的子序列。
//最佳子序列为最后 4 个元素组成的子序列。
HINT
Source
扫描 水题
又到了水题时间~
序列的gcd收敛得很快,好像有结论说不同的gcd不会超过log(序列长度)个
用map存一下当前存在的gcd最早在哪里出现,扫描一遍序列统计答案即可。
如果那个结论正确,复杂度大概是$ O(n log^2 n) $ (map自带一个log)
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<map> 7 #define LL long long 8 using namespace std; 9 const int mxn=100010; 10 LL read(){ 11 LL x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 LL gcd(LL a,LL b){return b?gcd(b,a%b):a;} 17 map<LL,int>mp,tmp; 18 map<LL,int>::iterator it; 19 int n; 20 LL a[mxn]; 21 int main(){ 22 // freopen("in.txt","r",stdin); 23 int i,j; 24 n=read(); 25 LL ans=0; 26 for(i=1;i<=n;i++){ 27 a[i]=read();ans=max(ans,a[i]); 28 for(it=mp.begin();it!=mp.end();it++){ 29 LL g=gcd((*it).first,a[i]); 30 ans=max(ans,g*(i-(*it).second+1)); 31 if(!tmp.count(g))tmp[g]=(*it).second; 32 else tmp[g]=min(tmp[g],(*it).second); 33 } 34 if(!tmp.count(a[i]))tmp[a[i]]=i; 35 mp=tmp; 36 tmp.clear(); 37 } 38 printf("%lld\n",ans); 39 return 0; 40 }
本文为博主原创文章,转载请注明出处。