题解 CF520E 【Pluses everywhere】

思路:

\(\quad\)这是一道数学题,分别计算每一个点分别作个位,十位... \(n-k\) 位的贡献即可(不可做这一数位的数的这一数位的贡献为 \(0\) ),如字符串 \(9876543210\)\(0\) 只可以作个位, \(1\) 只可以作个位和十位,其他数位的贡献为 \(0\) ,所以可以得到

\(ans=a_n \times C_{n-1}^{k} + a_{n-1}\times C_{n-2}^{k-1} + 10\times a_{n-1}\times C_{n-2}^k + a_{n-2}\times C_{n-2} + 10\times a_{n-2}\times C_{n-3}^{k-1} + 100\times a_{n-2}\times C_{n-3}^{k}.....\)

化简得:

\(ans =\sum_{i=1}^{n-k}(10^{i-1}\times (a_{n-i-1}\times C_{n-i}^{k})+\sum_{j=1}^{n-i}a_j\times C_{n-i-1}^{k-1})\)

\(\quad\)所以只需要用数组 \(b\) 记录前缀和,用数组 \(d\) 记录 \(1! - n!\) ,用数组 \(inv\) 记录每个阶乘的逆元,最后注意取模即可,很有价值的一题,建议式子再推一遍,尤其是边界。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
#define re register int
#define int long long
#define LL long long
#define il inline
#define lowbit(x) x&(-x)
#define next nee
#define inf 1e18
il int read()
{
  int x=0,f=1;char ch=getchar();
  while(!isdigit(ch)&&ch!='-')ch=getchar();
  if(ch=='-')f=-1,ch=getchar();
  while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
  return x*f;
}
il void print(int x)
{
  if(x<0)putchar('-'),x=-x;
  if(x/10)print(x/10);
  putchar(x%10+'0');
}
const int N=1e5+5,MOD=1e9+7;
int n,m,k,a[N],b[N],inv[N]={1,1},ans,d[N]={1};
string s;
il int C(int a,int b){return d[a]*inv[b]%MOD*inv[a-b]%MOD;}
signed main()
{
  n=read();k=read();cin>>s;int ret=1;
  for(re i=1;i<=n;i++)a[i]=s[i-1]-'0',b[i]=a[i]+b[i-1],d[i]=d[i-1]*i%MOD;//计算前缀和,阶乘 1!-n!
  for(re i=2;i<=n;i++)inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;//计算1-n每个数的逆元
  for(re i=2;i<=n;i++)inv[i]=inv[i]*inv[i-1]%MOD;计算1!-n!的逆元
  for(re i=1;i<=n-k;i++)
    {
      ans=(ans+ret*(a[n-i+1]*C(n-i,k)%MOD)%MOD)%MOD;
      ans=(ans+ret*(b[n-i]*C(n-i-1,k-1)%MOD)%MOD)%MOD;
      ret=ret*10%MOD; //ret表示10的i-1次方
      }
  print(ans);
  return 0;
}
posted @ 2020-11-23 22:05  Farkas_W  阅读(85)  评论(0编辑  收藏  举报