考虑从左往右填数,维护当前数字权值与$A$权值的差值,如果差值大于9,那么以后无论怎么填,都不会改变大小关系。
所以设$f[i][j][k]$表示填了前$i$位,差值为$j$,是否卡住$B$上限为$k$的方案数,然后DP即可。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=205,P=1000000007; int T,C,n,m,i,j,k,t,A[N],B[N],f[N][18][2],ans;char a[N],b[N]; inline void up(int&a,int b){a+=b;if(a>=P)a-=P;} int main(){ scanf("%d",&T); for(C=1;C<=T;C++){ scanf("%s%s",a+1,b+1);n=strlen(a+1);m=strlen(b+1); for(i=1;i<n-i+1;i++)swap(a[i],a[n-i+1]); for(i=1;i<m-i+1;i++)swap(b[i],b[m-i+1]); for(i=1;i<=n||i<=m;i++)A[i]=B[i]=0; for(i=1;i<=n;i++)A[i]=a[i]-'0'; for(i=1;i<=m;i++)B[i]=b[i]-'0'; if(n<m)n=m; for(i=1;i<n-i+1;i++)swap(A[i],A[n-i+1]),swap(B[i],B[n-i+1]); for(i=1;i<=n;i++)for(j=0;j<18;j++)f[i][j][0]=f[i][j][1]=0; for(i=0;i<=B[1];i++){ t=max(i-A[1],-9); if(t<9)f[1][t+9][i==B[1]]++; } for(i=1;i<n;i++)for(j=-9;j<9;j++){ for(k=0;k<=9;k++){ t=max(j*2-A[i+1]+k,-9); if(t<9)up(f[i+1][t+9][0],f[i][j+9][0]); } for(k=0;k<=B[i+1];k++){ t=max(j*2-A[i+1]+k,-9); if(t<9)up(f[i+1][t+9][k==B[i+1]],f[i][j+9][1]); } } for(ans=j=0;j<=9;j++)up(ans,f[n][j][0]),up(ans,f[n][j][1]); printf("Case #%d: %d ",C,ans); } return 0; }