BZOJ3588 : fx

考虑从左往右填数,维护当前数字权值与$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\n",C,ans);
  }
  return 0;
}

  

posted @ 2016-02-28 17:05  Claris  阅读(330)  评论(0编辑  收藏  举报