ABC379E 题解
ABC379E 题解
一道很好的题,开始还以为是高精度来着,但是发现不必要也不能用高精度,而是用一种技巧代替。
题意
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)\)
\(N\le 2\times 10^5\)
分析
很明显的可以找出一个递推式子来 \(dp[i]=dp[i-1]\times 10+i\times a[i]\)
然后最后的答案就是所有 \(dp\) 的和,但是这样做是会爆掉的,因为 \(N\) 比较大。
所以写高精度吗?然而是会超时的。
Tirick
对于这种输出的整数位数特别多的题目,可以直接考虑对每一位拆开按贡献来统计,比方说这道题里面,每个数字对个位的贡献分别都是 \(i\times a_i\) ;前 \(n-1\) 个数字对十位的贡献分别是 \(i\times a_i\) ......
所以我们可以想到做一个前缀和,然后从低位到高位模拟高精度就可以了。
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int n,a[N],dp[N],s[N];
int ans[N<<1],cnt;
signed main()
{
cin>>n;
for(int i=1;i<=n;++i)scanf("%1lld",&a[i]),a[i]=a[i]*i,s[i]=s[i-1]+a[i];
int tmp=0;
for(int i=n;i>=1;--i)
{
tmp+=s[i];
ans[++cnt]=tmp%10;
tmp/=10;
}
while(tmp)ans[++cnt]=tmp%10,tmp/=10;
for(int i=cnt;i;--i)cout<<ans[i];
return 0;
}
Extra
ABC233E 和这道题的思路很相似,可以做一下。
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int a[N],s[N],n=1;
int ans[N],cnt;
signed main()
{
while(scanf("%1lld",&a[n])!=EOF)s[n]=s[n-1]+a[n],n++;
n--;
int tmp=0;
int l=min(0ll,n-101);
for(int i=n;i>=1;--i)
{
tmp+=s[i]-s[l];
ans[++cnt]=tmp%10;
tmp/=10;
}
while(tmp)ans[++cnt]=tmp%10,tmp/=10;
for(int i=cnt;i>=1;--i)cout<<ans[i];
return 0;
}
本文来自博客园,作者:Hanggoash,转载请注明原文链接:https://www.cnblogs.com/Hanggoash/p/18537940