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;
}
posted @ 2024-11-10 14:49  Hanggoash  阅读(10)  评论(0编辑  收藏  举报
动态线条
动态线条end