Codeforces Round #675 (Div. 2) C. Bargain

文章转载自:https://blog.csdn.net/lmmmmmmmmmmmmmmm/article/details/108942614?utm_medium=distribute.pc_relevant.none-task-blog-title-1&spm=1001.2101.3001.4242

C. Bargain
Description

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 n, 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 1213121, Vova can remove the substring 1312, and the result is 121.

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

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 109+7.

Input

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

Output

In the only line print the required sum modulo 109+7.

Examples
input
107
output
42
input
100500100500
output
428101984
Note

Consider the first example.

Vova can choose to remove 1, 0, 7, 10, 07, or 107. The results are 07, 17, 10, 7, 1, 0. Their sum is 42.

题意: 给定一个数,求从它的任意位置删掉任意数后的所有情况的和。

题解: 我们可以对每一个数字逐个讨论,对于数字3,如果其有对最终结果做出贡献(即没有被去除的情况下),则有两种情况:①被去除的子串在3之前;②被除去的子串在3后面。
· 如果是第①种情况,3所占的位数始终是不变的,都是千位。共有6种可能:在这里插入图片描述

其中数字3做出的贡献就是3000×6=18000。而这个6是怎么来的呢?显然就是3+2+1=6。总结一下就是,对于下标为i(下标从0开始,从后往前遍历,总长设为len)的数字,第①种情况共有(len-i)(len-i-1)/2种可能,做出的贡献为(s[i]-‘0’)pow(10,i)(len-i)(len-i-1)/2,其中s是Sasha给出的价格,为字符串类型。
· 如果是第②种情况,同样有6种可能:在这里插入图片描述

数字3做出的贡献就是3×(3×100+2×10+1)=3×321=963(这里我们只看3所处的位置,不看其他数)。看着似乎也有些规律,来分析一下:如果一开始数字3后面有四个数,那么原式中的321就会变成4321。因此我们可以用变量sum来保存当前的要乘以的数,那么相对于下标为i的数字,做出的贡献为(s[i]-‘0’)sum,而每次循环之后sum如何变化,下面再讲。
这样我们就可以计算出每个数字对结果的贡献。但是还有一个问题,Sasha给出的价格的范围为 1 ≤ n < 1 0 5 1≤n<10^5 1n<105,根本没法计算,比如在第①种情况,(s[i]-‘0’)pow(10,i)(len-i)(len-i-1)/2中的pow(10,i)直接挂掉。这个时候我们就要对一些像10,100,1000之类的数字先做一遍取余,保存在数组f中,f[i]就表示pow(10,i)取余之后的结果,这样代码就会变成(len-i)(len-i-1)/2%MODf[i]*(s[i]-‘0’)%MOD;。而在第②种情况,sum显然也会挂掉,所以每次在更新sum的时候,也要对sum进行取余。而sum要如何变化呢?答案就是sum=((i+1)*f[i]%MOD+sum)%MOD;,想象从321到4321的过程,你一定能看懂这段代码。

c++ AC 代码

#include <cstdio>
#include <cstring>
#include <iostream>
typedef long long ll;
using namespace std;
const int mod = 1e9 + 7, N = 1e5 + 10;
char str[N];

int main()
{
	cin >> (str + 1);
	ll length = strlen(str + 1);
	ll ans = 0;
	ll pw = 1;
	ll sum = 0;
	for (ll i = length; i >= 1; i--)
	{
		ll num = i * (i - 1) / 2;
		ans = (ans % mod + (str[i] - '0') * pw % mod * num % mod) % mod; // 第一种情况
		ans = (ans % mod + (str[i] - '0') % mod * sum % mod) % mod;		 // 第二种情况
		sum = (sum % mod + (length - i + 1) * pw % mod) % mod;
		pw = pw * 10 % mod;
	}
	cout << ans << endl;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值