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
1through9.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
1through9.
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;
}

浙公网安备 33010602011771号