Codeforces Round #675 (Div. 2)C. Bargain(组合数学+贡献)

题意

去掉一段连续的区间后累加

思路

枚举每一位的贡献,假设该位没有被删除。

从左到右第(i)位,长度为(n)

假设删除该位前面连续的区间

[frac{1}{2}*(i-1)*i*str[i]*10^{n-i} ]

在前面任取一段连续的区间可能数为(C_i^2),乘以(str[i])的贡献

假设删除该位后面连续的区间

删除区间长度为(x)

[str[i]*sum_1^{n-i} (n-i-x+1)*10^{n-i-x} ]

通过代换可以转换为

[str[i]*sum_0^{n-i-1} (t+1)*10^t ]

#include<bits/stdc++.h>

using namespace std;
#define int long long

const int mod=1e9+7;

char str[100010];
int f[100010],p10[100010];
int res(int x){
    return x*(x-1)/2%mod;
}

void solve(){
    scanf("%s",str+1);
    int n=strlen(str+1);
    p10[0]=1;
    for(int i=1;i<=100005;++i){
        p10[i]=p10[i-1]*10;
        p10[i]%=mod;
    }
    f[0]=1;
    for(int i=1;i<=100005;++i){
        f[i]=f[i-1]+(i+1)*p10[i];
        f[i]%=mod;
    }
    int ans=0;
    for(int i=1;i<=n;++i){
        int pre=res(i)*(str[i]-'0')%mod*p10[n-i];
        int be=(str[i]-'0')*f[n-i-1];
        ans+=pre+be;
        ans%=mod;
    }
    printf("%lld
",ans);
}

signed main(){
    int t=1;
//    scanf("%lld",&t);
    while(t--){
        solve();
    }

}
原文地址:https://www.cnblogs.com/waryan/p/13771724.html