At379 E - Sum of All Substrings

E.Sum of All Substrings

原题链接

Problem Statement

You are given a string \(S\) of length \(N\) consisting of digits from 1 through 9.

For each pair of integers \((i,j) \ (1\leq i\leq j\leq N)\), define \(f(i, j)\) as the value obtained by interpreting the substring of \(S\) from the \(i\)-th through the \(j\)-th character as a decimal integer. Find \(\displaystyle \sum_{i=1}^N \sum_{j=i}^N f(i, j)\).

Constraints

  • \(1 \leq N \leq 2 \times 10^5\)
  • \(N\) is an integer.
  • \(S\) is a string of length \(N\) consisting of digits from 1 through 9.

Sample Input 1

3
379

Sample Output 1

514

The answer is \(f(1,1) + f(1,2) + f(1,3) + f(2,2) + f(2,3) + f(3,3) = 3 + 37 + 379 + 7 + 79 + 9 = 514\).

解题思路:

贡献法,单独考虑每一位对答案的贡献,记数字的第i位前面有i-1个数字,后面有n-i个元素,当前数字是x,由于要求连续,当前数字前面的数可以选(0,1,2,3,4...i-1)个,后面的数字每选一个当前位置贡献乘10,则显然(等比数列求和)其会产生(i+1)(1·(10n-i-1)/(10-1))x的贡献。
单纯这样显然会爆long long,考虑使用数组模拟大整数操作替换原先等比数列求和,将原本数组等比数列求和操作使用差分和后缀和累加,最后进行大整数逐位进位输出即可。

AC code:

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
ll num[200010];
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    int n;cin>>n;
    string s;cin>>s;
    s="&"+s;
    ll ans=0;
    for(int i=1;i<=n;i++){
        ll x=(s[i]^48);
        ll be=i-1;
        ll ed=n-i;
        num[i]=x*(be+1);
    }
    for(int i=1;i<=n;i++) num[i+1]+=num[i];
    for(int i=n;i>=1;i--){
        num[i-1]+=num[i]/10;
        num[i]%=10;
    }
    string res;
    for(int i=0;i<=n;i++){
        res.push_back(num[i]+'0');
    }
    //去除前导0
    reverse(res.begin(),res.end());
    while(res.size()>1&&res.back()=='0') res.pop_back();
    reverse(res.begin(),res.end());
    cout<<res<<endl;
    return 0;
}
posted @ 2025-05-17 09:09  usedchang  阅读(14)  评论(0)    收藏  举报