当前位置: 首页 > article >正文

洛谷U525322 优美区间

优美区间

题目描述

有一个长度为 n n n 的数字序列,序列的第 i i i 个数为 a i a_i ai

定义区间 [ l , r ] [l,r] [l,r] 的优美程度为 gcd ⁡ ( a l , a l + 1 , … , a r ) × ∑ i = l r a i \gcd(a_l,a_{l+1},\dots,a_r)\times\sum\limits_{i=l}^ra_i gcd(al,al+1,,ar)×i=lrai

你需要求出长度至少为 k k k 的区间的优美程度的最大值。

输入格式

第一行两个正整数 n , k n,k n,k

第二行 n n n 个正整数,第 i i i 个正整数为 a i a_i ai

输出格式

一行一个整数,表示答案。

样例 #1

样例输入 #1

7 2
2 1 5 4 4 4 2

样例输出 #1

48

提示

1 ≤ k ≤ n ≤ 1 0 6 1\le k\le n\le10^6 1kn106 1 ≤ a i ≤ 1 0 6 1\le a_i\le10^6 1ai106

注意到:对于一个 r r r,不同的 gcd ⁡ ( a l , a l + 1 , … , a r ) \gcd(a_l,a_{l+1},\dots,a_r) gcd(al,al+1,,ar) 至多只有 ⌊ log ⁡ a r ⌋ + 1 \lfloor\log a_r\rfloor+1 logar+1 种。

当我们对于一个 r = x r=x r=x 求出了所有不同的 gcd ⁡ ( a l , a l + 1 , … , a r ) \gcd(a_l,a_{l+1},\dots,a_r) gcd(al,al+1,,ar) 并找到了与之对应的最小的 l l l 后,要求出 r = x + 1 r=x+1 r=x+1 的情况。只需要在 l l l 的集合中插入 x + 1 x+1 x+1,并将对应的 gcd ⁡ \gcd gcd 相同的 l l l 只保留最小的即可。

于是对于每个 r r r,我们都可以求出所有不同的 gcd ⁡ ( a l , a l + 1 , … , a r ) \gcd(a_l,a_{l+1},\dots,a_r) gcd(al,al+1,,ar) 和与之对应的最小的 l l l,依次对这些区间中长度至少为 k k k 的区间计算优美程度,并取最大值即可。

时间复杂度为 Θ ( n log ⁡ 2 a ) \Theta(n\log^2 a) Θ(nlog2a),常数较小,可以通过本题。精细实现或使用科技可以做到 Θ ( n log ⁡ a ) \Theta(n\log a) Θ(nloga) 的复杂度。

暴力思路

常规暴力思路很容易想,但是拿不到满分。即遍历每一个可能的区间,同时计算gcd。
但是这样时间复杂度是 O ( n 2 log ⁡ a ) O(n^2 \log a) O(n2loga)级的。

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
typedef long long ll;
using namespace std;
int a[1000005],p[1000005];
// int g[1000005];
signed main() {
    cin.tie(0)->ios::sync_with_stdio(0);
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        p[i]=a[i]+p[i-1];
    }   

    int ans = 0;
    for (int i = 1; i <= n - k + 1; i++) {
        int g = a[i];
        for (int j = i; j <= n; j++) {
            g = __gcd(g, a[j]);
            if (j - i + 1 >= k) {
                int sum = p[j] - p[i - 1];
                int tans = g * sum;
                ans = max(ans, tans);
            }
        }
    }

    cout << ans << endl;
    return 0;
}
AC代码:
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
typedef long long ll;
using namespace std;
int a[1000005],p[1000005];
int g[1000005];  //存储左端点gcd
int pos[1000005]; //存储左端点位置
signed main() {
    cin.tie(0)->ios::sync_with_stdio(0);
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i];  
        p[i]=a[i]+p[i-1]; // 前缀和
    }   

    int ans = 0;
    int cnt = 0;
    for (int i = 1; i <= n; i++) { // 枚举右端点i
        pos[++cnt]=i;  // 将右端点本身添加进左端点的集合中
        g[cnt]=a[i];
        int tcnt = cnt;
        cnt = 0;
        for (int j = 1; j <= tcnt; j++) {//枚举左端点j
            g[j]=__gcd(g[j],a[i]); // 每个左端点与a[i]gcd
            if(g[j]!=g[cnt]){  // 重新计数 保存每个gcd最小左端点信息
                pos[++cnt]=pos[j];
                g[cnt]=g[j];
                if ( i - pos[j] + 1 >= k) { // 长度满足条件就更新答案
                    int sum = p[i] - p[pos[j]-1];
                    int tans = g[j] * sum;
                    ans = max(ans, tans);
                }
            }
        }
    }

    cout << ans << endl;
    return 0;
}

http://www.kler.cn/a/523884.html

相关文章:

  • Spring Boot - 数据库集成05 - 集成MongoDB
  • git中有关old mode 100644、new mode 10075的问题解决小结
  • 【每日一A】2015NOIP真题 (二分+贪心) python
  • three.js用粒子使用canvas生成的中文字符位图材质
  • 哈工大:LLM高质量嵌入模型KaLM-Embedding
  • Openfga 授权模型搭建
  • PHP EOF (Heredoc) 详解
  • 《多阶段渐进式图像修复》学习笔记
  • centos7安装SVN
  • Unity游戏(Assault空对地打击)开发(1) 创建项目和选择插件
  • LCD液晶屏的工作原理以及背光模组
  • 揭示Baklib企业内容管理系统CMS的核心功能与应用价值
  • 【Rust自学】16.3. 共享状态的并发
  • 学历赋
  • 动态规划DP 数字三角形模型(模型分析+例题分析+C++代码实现)(数字三角形、摘花生、最低通行费用、方格取数、传纸条)
  • 物联网工程与网络工程到底有什么关系?
  • 探索人工智能在计算机视觉领域的创新应用与挑战
  • games101-作业
  • 国内外大语言模型领域发展现状与预期
  • 硬件学习笔记--35 AD23的使用常规操作
  • HTB:Forest[WriteUP]
  • 算法随笔_19: 数组中的最长山脉
  • DeepSeek助力学术文献搜索!
  • 安装VMware17
  • SQL进阶实战技巧:如何构建用户行为转移概率矩阵,深入洞察会话内活动流转?
  • JavaScript系列(45)--响应式编程实现详解