題解 CF520E 【Pluses everywhere】
阿新 • • 發佈:2020-11-24
思路:
\(\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; }