CF1422C Bargain (DP+思维+数学)

链接

题意:

给定整数 n ( 1 ≤ l e n ( n ) < 1 0 5 n(1 \leq len(n) < 10^5 n(1len(n)<105 ,其中 l e n ( n ) len(n) len(n)表示 n n n 的位数)) ,现在规定每一轮Vova可以从中取出一段连续的几位数字,剩余数字即为该轮得分.结果可以拥有前导 0 0 0 .特别的,如果Vova取出了所有数字,那么该轮得分为 0 0 0 .

现在请你求出所有不同取法得分之和对 1 0 9 + 7 10^9+7 109+7取模后的值.特别的,如果有多种不同取法得到了同样的数字,得分要计多次.

分析:

首先我们对第i位上的数进行分析,看看他能做出多少贡献:
他做出贡献的方式有两种(三种):

  • 删除i位前面的数
  • 删除i位后面的数
  • 删除包含i位连续的一段数(删了不作出贡献)

那么我们分析删除i位前面的数做出的贡献: 首先肯定的是删除i位之前,i位的贡献是不变的,都是 s t r [ i ] ∗ 1 0 l e n − i + 1 str[i]*10^{len-i+1} str[i]10leni+1然后我们只需要算计算多少次就行,就看前面那一段数删出区间有多少种?从前(i-1)个数种选出2个数当左右区间即可也就是(i-1)*i/2.

然后看删除i位后面的数做出的贡献:同删除i位前面的数分析,不同的是i位的贡献是变化的,我们发现他贡献是这样变化的1,20,300,4000…,因为每当他后面多一位就多了一种选择。

/// 欲戴皇冠,必承其重。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
typedef unsigned long long ull;

#define x first
#define y second
#define PI acos(-1)
#define inf 0x3f3f3f3f
#define lowbit(x) ((-x)&x)
#define debug(x) cout << #x << ": " << x << endl;

const int MOD = 998244353;
const int mod = 1e9+7;
const int N = 5e5 + 10;
const int dx[] = {0, 1, -1, 0, 0, 0, 0};
const int dy[] = {0, 0, 0, 1, -1, 0, 0};
const int dz[] = {0, 0, 0, 0, 0, 1, -1};
int day[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

ll n, m,p;
string str;

void solve()
{
    cin>>str;
    ll len=str.size();
    str=" "+str;
    ll ans=0;
    ll sum=0;
    p=1;
    for(ll i=len;i>=1;i--){
        ll now = (i-1)*i/2;
        ans = (ans+p*(str[i]-'0')%mod*now%mod)%mod;///只删前面】
        ans = (ans + sum * (str[i]-'0') % mod ) % mod;///只删后面
        sum = (sum + (len-i+1) *p %mod) % mod;
        p = p * 10 % mod;
    }
    printf("%lld\n",ans);
}    
int main()
{
    ll t = 1;
    ///scanf("%lld", &t);
    while(t--)
    {
        solve();
    }
    return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值