• COCI2022-2023#1 Neboderi


    P9032 [COCI2022-2023#1] Neboderi

    题目大意

    有一个长度为 n n n的序列 h i h_i hi,你需要从中选择一个长度大于等于 k k k的子区间 [ l , r ] [l,r] [l,r],使得 g × ( h l + h l + 1 + ⋯ + h r ) g\times (h_l+h_{l+1}+\cdots+h_r) g×(hl+hl+1++hr)最小,其中 g = gcd ⁡ ( h l , h l + 1 , … , h r ) g=\gcd(h_l,h_{l+1},\dots,h_r) g=gcd(hl,hl+1,,hr)

    1 ≤ k ≤ n ≤ 1 0 6 , 1 ≤ h i ≤ 1 0 6 1\leq k\leq n\leq 10^6,1\leq h_i\leq 10^6 1kn106,1hi106


    题解

    当确定了 l l l时, gcd ⁡ ( h l , h l + 1 , … , h r ) \gcd(h_l,h_{l+1},\dots,h_r) gcd(hl,hl+1,,hr)随着 r r r的增大而减小。

    每当 gcd ⁡ \gcd gcd减小时,其 gcd ⁡ \gcd gcd相对于原来的 gcd ⁡ \gcd gcd肯定有若干个质因数的次数减小。那么,对于一个确定的 l l l gcd ⁡ ( h l , h l + 1 , … , h r ) \gcd(h_l,h_{l+1},\dots,h_r) gcd(hl,hl+1,,hr)的取值不会超过 log ⁡ a l \log a_l logal个数。

    先用 S T ST ST表维护区间 gcd ⁡ \gcd gcd。枚举 l l l,在二分每一段 g c d gcd gcd值相等的区间并取该区间的右端点作为 r r r来更新答案。

    v v v a i a_i ai的最大值,则时间复杂度为 O ( n log ⁡ n log ⁡ v ) O(n\log n\log v) O(nlognlogv)

    当然,这是跑不满的,而且时限为 2.50 s 2.50s 2.50s,所以可以过。


    code

    #include
    #include
    using namespace std;
    const int N=1000000;
    int n,k,now,v[N+5],lg[N+5],f[N+5][20];
    long long ans=0,sum[N+5];
    int gcd(int i,int j){
    	while(j){
    		i%=j;swap(i,j);
    	}
    	return i;
    }
    int gt(int l,int r){
    	int x=lg[r-l+1];
    	return gcd(f[l][x],f[r-(1<<x)+1][x]);
    }
    int to(int w,int be,int hv){
    	int l=be+1,r=n,mid;
    	while(l<=r){
    		mid=l+r>>1;
    		if(gt(w,mid)>=hv) l=mid+1;
    		else r=mid-1;
    	}
    	return l-1;
    }
    int main()
    {
    	scanf("%d%d",&n,&k);
    	lg[0]=-1;
    	for(int i=1;i<=n;i++){
    		lg[i]=lg[i/2]+1;
    		scanf("%d",&v[i]);
    		sum[i]=sum[i-1]+v[i];
    		f[i][0]=v[i];
    	}
    	for(int i=1;i<=19;i++){
    		for(int j=1;j<=n-(1<<i-1);j++){
    			f[j][i]=gcd(f[j][i-1],f[j+(1<<i-1)][i-1]);
    		}
    	}
    	for(int l=1,r;l<=n-k+1;l++){
    		now=gt(l,l+k-1);
    		r=to(l,l+k-1,now);
    		while(r<=n){
    			ans=max(ans,gt(l,r)*(sum[r]-sum[l-1]));
    			if(r==n) break;
    			now=gt(l,r+1);
    			r=to(l,r+1,now);
    		}
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
  • 相关阅读:
    Python配置镜像源
    [Git] 系列四Push & Pull —— Git 远程仓库和高级操作
    (附源码)计算机毕业设计Java办公自动化管理系统
    小谈设计模式(15)—观察者模式
    【Js】导出 HTML 为 Word 文档
    Ring Buffer 如何实现
    Java.lang.Character类中isUpperCase()方法具有什么功能呢?
    mysql中的分页查询的优化方案
    C语言|图解指针变量
    vue、js获取页面中所有css样式(包括link标签)案例为打印使用
  • 原文地址:https://blog.csdn.net/tanjunming2020/article/details/133522258