• CodeForces-520E Pluses everywhere


    题目描述

    给出一个长度为 (n) 的字符串,给出一个非负整数 (k),要求给这个字符串中间添加 (k) 个$$+$’号,变成一个表

    达式,比如”(1000101)”,添加两个(+)号,可以变成”(10+001+01)”,或者”(1000+1+01)”,表达式的值分别是(12)(1002)

    问所有的添加加号的方案的表达式的值的和是多少。

    Input

    两个整数 (n,k),一个字符串$ s$ ((0<=k<n<=1e5).)

    Output

    一个整数,模$ 1000000007$

    Sample Input

    3 1
    108
    
    3 2
    108
    

    Sample Output

    27
    9
    

    计数(DP)

    首先,看到那么大的数据范围肯定是对于每个数计算贡献。

    那么我们该如何计算贡献呢?

    对于题目给出的那个字符串(S),从左往右每个数字依次为(a_{n-1},a_{n-2}....a_{1},a_0).

    现在,我们对于(a_t),讨论其贡献。

    (a_t)右边有(t)个位置可以放置加号,同时一共有(n-1)个位置放置加号。

    (a_t)右边第一个位置放置了加号,则(a_t)被当成个位,还有(n-2)个空位,(k-1)个加号,一共有(C(k-1,n-2))种方案。

    其贡献为(C(k-1,n-1)*10^{0}*a_t)

    (a_t)右边第一个位置为空,第二个位置放置加号,则(a_t)为十位,还有(n-3)个空位,(k-1)个加号,共有(C(k-1,n-3))种方案。

    贡献为(C(k-1,n-2)*10^{1}*a_t).

    依次类推,

    (a_t)右边为空,则贡献为(C(k,n-t-2)*10^{t}*a_t)

    所以,(a_t)这个数的贡献为((10^{t}*C(k,n-t-2)+sum^{t}_{j=0}10^{j}*C(k-1,n-j-2))*a_t)

    于是我们可以得到第(i)个数的贡献计算公式(A_i=10^{i}*C(k,n-i-2)+sum^{i}_{j=0}10^{j}*C(k-1,n-j-2))

    最后,(Ans=sum^{n-1}_{i=0}A_i*a_i)

    代码如下

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define int long long
    #define reg register
    #define Raed Read
    #define clr(a,b) memset(a,b,sizeof a)
    #define Mod(x) (x>=mod)&&(x-=mod)
    #define debug(x) cerr<<#x<<" = "<<x<<endl;
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)>(b)?(b):(a))
    #define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
    #define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
    #define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
    #define erep(i,G,x) for(int i=(G).Head[x]; i; i=(G).Nxt[i])
    #pragma GCC target("avx,avx2,sse4.2")
    #pragma GCC optimize(3)
    
    inline int Read(void) {
    	int res=0,f=1;
    	char c;
    	while(c=getchar(),c<48||c>57)if(c=='-')f=0;
    	do res=(res<<3)+(res<<1)+(c^48);
    	while(c=getchar(),c>=48&&c<=57);
    	return f?res:-res;
    }
    
    template<class T>inline bool Min(T &a, T const&b) {
    	return a>b?a=b,1:0;
    }
    template<class T>inline bool Max(T &a, T const&b) {
    	return a<b?a=b,1:0;
    }
    
    
    const int N=1e5+5,M=1e6+5,mod=1e9+7;
    
    bool MOP1;
    
    int Fac[N],Inv[N];
    
    inline int Pow(int x) {
    	int res=1,y=mod-2;
    	while(y) {
    		if(y&1)res=(res*x)%mod;
    		x=(x*x)%mod,y>>=1;
    	}
    	return res;
    }
    
    inline int C(int x,int y) {
    	if(!x)return 1;
    	return (Fac[y]*((Inv[x]*Inv[y-x])%mod))%mod;
    }
    
    int A[N],Pow_10[N];
    
    char S[N];
    
    bool MOP2;
    
    inline void _main() {
    	int n=Read(),k=Read(),Ans=0,tot=0;
    	scanf("%s",S),Fac[0]=Pow_10[0]=Inv[0]=1;
    	if(!k) {
    		int Ans=0;
    		ret(i,0,n)Ans=(Ans*10+(S[i]^48))%mod;
    		printf("%lld
    ",Ans);
    		return;
    	}
    	rep(i,1,n) {
    		Fac[i]=(Fac[i-1]*i)%mod;
    		Pow_10[i]=(Pow_10[i-1]*10)%mod;
    		Inv[i]=Pow(Fac[i]);
    	}
    	A[0]=C(k-1,n-2);
    	int P=n-k-1;
    	rep(i,0,P)A[i]=(A[i-1]+Pow_10[i]*C(k-1,n-i-2))%mod;
    	rep(i,P+1,n)A[i]=A[i-1];
    	rep(i,0,P)A[i]=(A[i]+Pow_10[i]*C(k,n-i-2));
    	ret(i,0,n)Ans=(Ans+(S[i]^48)*A[n-i-1])%mod;
    	printf("%lld
    ",Ans);
    }
    
    signed main() {
    	_main();
    	return 0;
    }
    
  • 相关阅读:
    轻松搭建CAS 5.x系列(7)-在CAS Server使用第三方帐号做认证
    轻松搭建CAS 5.x系列(6)-在CAS Server上增加OAuth2.0协议
    轻松搭建CAS 5.x系列(5)-增加密码找回和密码修改功能
    CAS 5.x搭建常见问题系列(3).Failure to find org.apereo.cas:cas-server-support-pm-jdbc:jar:5.1.9
    CAS 5.x搭建常见问题系列(2).PKIX path building failed
    CAS 5.x搭建常见问题系列(1).未认证的授权服务
    轻松搭建CAS 5.x系列(4)-Java客户端程序接入CAS单点登录,Hello World版
    轻松搭建CAS 5.x系列文章
    CAS实现SSO单点登录-CAS Server 5.3搭建 cas5.3搭建 cas5.3去除https cas 去除https cas 5.x 去除https
    互联网大咖都要收藏的几个网站,纯干货
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11402180.html
Copyright © 2020-2023  润新知