题意:
把 [i,j] 这个区间的数翻转一下和剩下的 n−j+i−1 个数形成一个新的大数,求所有翻转以后的数的和。
分析:
翻转以后的数由原来的数和翻转部分的数组成。暴力枚举
i
开始的所有新的数的和。
那么
ans[i]=∑j=in(r[1]−r[i−1])+r[j+1]+l[j]−l[i−1]10i−1∗10n−j
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 100010;
const int Mod = 1e9+7;
LL quickpow(LL x,int n,int Mod){
LL ans = 1;
while(n){
if(n%2) ans = ans*x%Mod;
x = x*x%Mod;
n >>= 1;
}
return ans;
}
int n;
char str[maxn];
LL bit[maxn],inv[maxn],l[maxn],r[maxn],suml[maxn],sumr[maxn],sum[maxn];
LL calc(int i){
LL ans = (r[1]-r[i]+Mod)*(n-i+1)%Mod;
ans += (suml[n]-suml[i-1]+Mod)*bit[n-i+1]%Mod;
ans %= Mod;
LL tem = bit[n-i+1]*l[i-1]%Mod*(sum[n]-sum[i-1]+Mod)%Mod;
ans = (ans+Mod-tem)%Mod;
ans = (ans+sumr[n]-sumr[i]+Mod)%Mod;
return ans;
}
void work(){
LL ans = 0;
for(int i = 1;i <= n;++ i){
//cout << "calc:" << calc(i) << endl;
ans += calc(i);
ans %= Mod;
}
printf("%lld\n",ans);
}
int main(){
//freopen("test.in","r",stdin);
bit[0] = 1; for(int i = 1;i < maxn;++ i) bit[i] = bit[i-1]*10%Mod;
LL tem = quickpow(10,Mod-2,Mod);
sum[0] = 0;
inv[0] = 1; for(int i = 1;i < maxn;++ i) inv[i] = inv[i-1]*tem%Mod;
for(int i = 1;i < maxn;++ i) sum[i] = (sum[i-1]+inv[i])%Mod;
while(~scanf("%d",&n)){
scanf("%s",str+1);
l[0] = 0; r[0] = 0;
l[n+1] = r[n+1] = 0;
for(int i = 1;i <= n;++ i){
l[i] = (l[i-1]+(str[i]-'0')*bit[i-1])%Mod;
}
for(int i = n;i >= 1;-- i){
r[i] = (r[i+1]+(str[i]-'0')*bit[n-i])%Mod;
}
suml[0] = sumr[0] = 0;
suml[n+1] = sumr[n+1] = 0;
for(int i = 1;i <= n;++ i){
suml[i] = (suml[i-1]+inv[i]*l[i])%Mod;
sumr[i] = (sumr[i-1]+r[i])%Mod;
}
/*
cout << "l:";
for(int i = 1;i <= n;++ i) cout << l[i] << " ";
cout << endl;
cout << "suml:";
for(int i = 1;i <= n;++ i) cout << suml[i] << " ";
cout << endl;
cout << "r:";
for(int i = 1;i <= n;++ i) cout << r[i] << " ";
cout << endl;
cout << "sumr:";
for(int i = 1;i <= n;++ i) cout << sumr[i] << " ";
cout << endl;
*/
work();
}
return 0;
}