长序列

解题思路

问题分析:
题目给出了一个长度为N的序列A,将其重复连接10^100次得到序列B。要求找出最小的k,使得B的前k项之和首次超过给定的X值。

关键观察:

  1. 由于B是A的无限循环,我们可以利用周期性来优化计算。
  2. 首先计算一个完整周期(即整个A序列)的和S = sum(A)。
  3. 计算完整的周期数m = X // S,这部分贡献了m * N个元素。
  4. 剩下的余数X % S需要在当前周期内找到最小的k2,使得前k2项之和超过这个余数。
  5. 最终答案就是m * N + k2。

优化点:

  • 使用前缀和数组s[]来快速计算部分和。
  • 通过模运算减少不必要的重复计算。

代码注释

#include<bits/stdc++.h>
using namespace std;
#define ll long long  // 定义long long类型别名
const int N = 1e5+5;   // 定义数组最大长度

ll n, x;               // n-序列长度,x-目标和
ll a[N], s[N];         // a-原始序列,s-前缀和数组

int main() {
    // 输入序列长度n
    cin>>n;
    
    // 输入序列并计算前缀和
    for(int i=1;i<=n;i++){
        cin>>a[i];
        s[i] = s[i-1] + a[i];  // s[i]表示前i项的和
    }
    
    // 输入目标和x
    cin>>x;
    
    // 计算完整周期的贡献
    // k = 完整周期数 * 每个周期的元素数
    ll k = x/s[n] * n;
    
    // 计算剩余部分
    x %= s[n];
    
    // 在当前周期内寻找最小的k2使得和超过x
    int k2= 0;
    for(int i=1;i<=n;i++){
        if(s[i]>x){     // 当部分和超过剩余x时
            k2 = i;     // 记录位置
            break;       // 找到后立即退出
        }
    } 
    
    // 总元素数 = 完整周期贡献 + 当前周期内需要的元素数
    k += k2;
    
    // 输出结果
    cout<<k;
    
    return 0;
}

代码解释

  1. 输入处理:

    • 读取序列长度n
    • 读取序列元素并同时计算前缀和数组s[]
  2. 周期计算:

    • k = x/s[n] * n 计算完整周期贡献的元素数量
    • x %= s[n] 计算剩余需要处理的部分和
  3. 剩余部分处理:

    • 遍历前缀和数组,找到第一个超过剩余x的位置k2
  4. 结果输出:

    • 将完整周期贡献和剩余部分贡献相加得到最终结果k

该算法的时间复杂度为O(N),能够高效处理题目给出的最大约束条件(N ≤ 1e5)。通过利用周期性性质和前缀和优化,避免了不必要的重复计算。

posted @ 2025-05-13 16:14  季风起  阅读(2)  评论(0)    收藏  举报