题目大意
设
F(x)=X数位的卷积
,求
∑F(1..n)
n<=1018
想法
首先10^18肯定是 log 解的
我们按照数位DP的思想,去考虑10^(k-1)~10^k-1的F(i)和
0~9:
1*1+2*2+3*3… = 285
10~99:
XX ,考虑这一对的贡献,那就是两倍的
1*1+1*2+1*3…+1*9 + 2*1+2*2+2*3+….9*1
=2*(1*45+2*45+3*45…9*45)
=2*45*45
100~999:
XXX 先考虑那一对的贡献,2*45*45*10 ,就是相当于XX中间再插一个数。
再考虑中间的贡献,左右两边最高位9种,最低位10种,共9*10*285
… 以此类推。
然后呢,对于一个数比如32074
我们先做0~29999
就相当于,万位有0~2=3种可能,其他位10种,按照上面的计算即可
再做30000~31999
万位1种可能 ,千位0~2两种可能,其他位10种,
以此类推即可。
CODE
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cmath>
#define MO 1000000007LL
#define M(x,y) ((y)-(x)+1)
typedef long long ll;
using namespace std;
ll l,r;
ll num[20],can[20],numst[20],numed[20],tmpnum[20];
void resolve(ll x, ll* o) {
for (ll kk=0; kk<20; kk++) o[kk]=0;
while (x>0) {
o[++o[0]]=x%10;
x/=10;
}
}
ll F(ll x) {
ll rt=0;
resolve(x,num);
long long ed=0;
ll st=0,p2,p,s;
ll maybe=0;
ll b=10;
while (b<=x) {
resolve(b-1,tmpnum);
for (ll j=1; j<=tmpnum[0]/2; j++) {
maybe=1;
for (ll k=1; k<=tmpnum[0]; k++) {
if (k != j && k != M(j,tmpnum[0])) {
if (k==tmpnum[0]) {
maybe=maybe*9%MO;
} else {
maybe=maybe*10%MO;
}
}
}
rt=(rt+maybe%MO*2*45*45%MO)%MO;
}
if (tmpnum[0]%2) {
maybe=1;
for (ll k=1; k<=tmpnum[0]; k++){
if (k != tmpnum[0]/2+1) {
if (k==tmpnum[0]) {
maybe=maybe*9%MO;
} else {
maybe=maybe*10%MO;
}
}
}
rt=(rt+maybe%MO*285%MO)%MO;
}
b*=10;
if (b==1000000000000000000) break;
}
st=b/10;
for (ll i=num[0]; i>0; i--) {
ed+=((ll)pow(10,i-1))*num[i];
if (i==num[0]) ed--;
if (i==1) ed++;
if (st>ed) continue;
if (ed>x) continue;
resolve(st,numst);
resolve(ed,numed);
for (ll i=1; i<=numed[0]; i++) can[i]=numed[i]-numst[i]+1;
if (numst[numed[0]]==0) can[numed[0]]--;
for (ll j=1; j<=numed[0]/2; j++) {
p=0;
for (ll k=numst[j]; k<=numed[j]; k++) {
p+=k;
}
p2=0;
for (ll k=numst[M(j,numed[0])]; k<=numed[M(j,numed[0])]; k++) {
p2+=k;
}
maybe=1;
for (ll k=1; k<=numed[0]; k++) {
if (k != j && k != M(j,numed[0])) {
maybe=maybe*can[k]%MO;
}
}
rt=(rt+2*p*p2%MO*maybe%MO)%MO;
}
if (numed[0]%2) {
maybe=1;
s=0;
for (ll k=numst[numed[0]/2+1]; k<=numed[numed[0]/2+1]; k++) {
s+=k*k;
}
for (ll k=1; k<=numed[0]; k++){
if (k != numed[0]/2+1) {
maybe=maybe*can[k]%MO;
}
}
rt=(rt+s%MO*maybe%MO)%MO;
}
st=ed+1;
}
return rt%MO;
}
int main() {
cin>>l>>r;
cout<< (F(r)+MO-F(l-1))%MO <<endl;
}