Description
Analysis
我跑得好慢sosad
发现自己基础不扎实,于是。。。
我用的是标准题解法,枚举两个位,枚举分别填的数,再数位DP一下算满足条件的数有多少个
数位DP的细节极多。。。
f[i][j][01]表示第i位,填j,是否贴着上界的数有多少个。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,b,a) for(int i=b;i>=a;i--)
using namespace std;
typedef long long ll;
const ll mo=1e9+7;
int a[20],f[20][10][2];
ll dp(int n,int i1,int j1,int x,int y)
{
memset(f,0,sizeof(f));
fo(j,1,9)
{
if(i1==n && j!=x || j1==n && j!=y) continue;
if(n==a[0])
{
if(j>a[n]) break;
if(j==a[n]) f[n][j][0]=1;
else f[n][j][1]=1;
}
else f[n][j][1]=1;
}
fd(i,n-1,1)
{
if(!(i1==i && x!=a[i] || j1==i && y!=a[i])) (f[i][a[i]][0]+=f[i+1][a[i+1]][0])%=mo;
fo(j,0,9)
{
if(i1==i && j!=x || j1==i && j!=y) continue;
fo(k,0,9)
{
(f[i][j][1]+=f[i+1][k][1])%=mo;
if(j<a[i] && k==a[i+1]) (f[i][j][1]+=f[i+1][k][0])%=mo;
}
}
}
ll t=f[1][a[1]][0];
if(i1==1) t=f[1][x][0];
fo(j,0,9)
{
if(i1==1 && j!=x || j1==1 && j!=y) continue;
(t+=f[1][j][1])%=mo;
}
return t;
}
ll solve()
{
ll s=0;
fo(i,1,a[0])
fo(j,i,a[0])
{
int w=i+j-1;
if(w>a[0]) continue;
fo(x,1,9)
fo(y,1,9)
{
if(i==j && x!=y) continue;
if(j==a[0] && y>a[a[0]]) break;
ll t=x*y*dp(w,i,j,x,y)%mo;
if(i==j) s=(s+t)%mo;
else s=(s+t*2%mo)%mo;
}
}
return s;
}
int main()
{
ll x,ans;
scanf("%lld",&x);x--;
for(;x;x/=10) a[++a[0]]=x%10;
ans=solve();
scanf("%lld",&x);
a[0]=0;
for(;x;x/=10) a[++a[0]]=x%10;
ll t=solve();
ans=(t-ans+mo)%mo;
printf("%lld",ans);
return 0;
}