CF1422C Bargain

题目描述

Sometimes it is not easy to come to an agreement in a bargain. Right now Sasha and Vova can't come to an agreement: Sasha names a price as high as possible, then Vova wants to remove as many digits from the price as possible. In more details, Sasha names some integer price nn , Vova removes a non-empty substring of (consecutive) digits from the price, the remaining digits close the gap, and the resulting integer is the price.

For example, is Sasha names 12131211213121 , Vova can remove the substring 13121312 , and the result is 121121 .

It is allowed for result to contain leading zeros. If Vova removes all digits, the price is considered to be 00 .

Sasha wants to come up with some constraints so that Vova can't just remove all digits, but he needs some arguments supporting the constraints. To start with, he wants to compute the sum of all possible resulting prices after Vova's move.

Help Sasha to compute this sum. Since the answer can be very large, print it modulo 10^9 + 7109+7 .

输入格式

The first and only line contains a single integer nn ( 1 \le n < 10^{10^5}1≤n<10105 ).

输出格式

In the only line print the required sum modulo 10^9 + 7109+7 .

题意:

给一串数字,数字的长度是1e5

我们可以删除他任意连续长度的子串,剩下的数字组成新一个数。

求删除子串之后的所有情况的数的总和。

思路:我们看每一位对总数的贡献。比如例子:1213121

我们先将他逆转(以便能更好的计算每一位做的贡献)

我们以3举例:

 如果3要是对整个数有贡献,那么有两种情况:

1.删除的子串要么在3的前面    2.删除的子串在3的后面。

对于情况1:

 红色代表删除的部分。黑色代表留下的部分。

那么3对总数的贡献都没变,就是3*pow(10,i)

那么这种情况有3+2+1=6种,就是看前面有几位数然后从1加到那个数:1+2+...+len-i-1

所以对情况1来说我们总结的a[i]对于总数的贡献就是:

a[i]*pow(10,i)*(len-i-1)*(len-i)/2.

对于情况2:

 那么3的位数在变化

当去掉3位的情况有1种,对整体的贡献是pow(10,0):1*pow(10,0)

去掉2位的情况有2种,对整体的贡献是pow(10,1):2*pow(10,1)

去掉1位的情况有3种,对整体的贡献是pow(10,2):3*pow(10,2)

而且对3右面的1来说:

去掉2位的情况有1种,对整体的贡献是pow(10,0):1*pow(10,0)

去掉1位的情况有2种,对整体的贡献是pow(10,1):2*pow(10,1)

那么我们就可以递推着来算贡献的位数

设i-1位对总数的贡献是tmp[i-1],那么第i位对总数的贡献就是:

tmp[i]=tmp[i-1]+i*pow(10,i-1)

然后拿这个位数乘上a[i]就是右边所有数对总数的贡献:a[i]*tmp

还有要注意的就是题目给的mod是1e9+7,那么这个数的长度是1e5的话pow(10,i)到最后肯定会超出范围,那么我们就先预处理一下数组f[i]来记录10^i%mod的数到时候直接用就行。

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;
typedef long long ll;
string s;
const int N=1e5+5;
ll f[N];
const ll mod=1e9+7;
int main(){
	cin>>s;
	f[0]=1;
	for(int i=1;i<N;i++){
		f[i]=f[i-1]*10%mod;
	}
	reverse(s.begin(),s.end());
	ll ans=0;
	ll len=s.size();
	ll tmp=0;
	for(int i=0;i<len;i++){
		ll num1=(len-i-1)*(len-i)/2%mod*f[i]*(s[i]-'0')%mod;
		ll num2=(s[i]-'0')*tmp%mod;
		tmp=((i+1)*f[i]%mod+tmp)%mod;
		ans+=(num1+num2)%mod;
		ans%=mod;
	}
	cout<<ans;
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值