本题目,一些位置给了一个 a+b=c的表达式,其中a,b,c的一些位用?表示。问有多少种填数方式,让表达式成立。
首先,要说明的是状态表示d[ i ][ j ][ k ][ p ]表示三个数的p位置为i , j ,k, 则可能有两种情况(i+j)%10==k | | ( i+j+1)%10==k,因为只有这两种情况下的状态才具有意义。
那么转移,也就很清楚了,第一种情况不依赖进位,而第二种情况依赖进位。
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep(i,n) for(int (i)=0;(i)<(n);i++) #define Rep(i,n) for(int (i)=1;(i)<=(n);i++) const int N = 15; int la[2],lc,ans[3]; LL d[N][N][N][N]; char a[2][N],c[N]; int judge(int kk,int p){ if(p==lc-1&&lc>1){ if(kk>=1){ if(c[p]=='?'|| (c[p]-'0'==kk&&c[p]!='?')) return 1; } return 0; } else if(c[p]=='?'|| (c[p]-'0'==kk&&c[p]!='?')) return 1; return 0; } LL dp(int i,int j,int k,int p){ if(d[i][j][k][p]!=-1) return d[i][j][k][p]; LL& ans=d[i][j][k][p]; if(p==0){ if((i+j)%10==k) return ans=1; return ans=0; } int st[2],ed[2]; rep(ii,2){ if(la[ii]>p-1){ if(a[ii][p-1]=='?') st[ii]=0,ed[ii]=9; else st[ii]=ed[ii]=a[ii][p-1]-'0'; } else st[ii]=ed[ii]=0; if(p-1==la[ii]-1 && la[ii]>1 && a[ii][p-1]=='?') st[ii]=1; } ans =0; for(int ii=st[0];ii<=ed[0];ii++) for(int jj=st[1];jj<=ed[1];jj++){ if((i+j)%10==k){ if((ii+jj)/10==0&&judge(ii+jj,p-1)) ans+=dp(ii,jj,ii+jj,p-1); if((ii+jj+1)/10==0&&judge(ii+jj+1,p-1)) ans+=dp(ii,jj,ii+jj+1,p-1); } else if((i+j+1)%10==k){ if((ii+jj)/10==1&&judge((ii+jj)%10,p-1)) ans+=dp(ii,jj,(ii+jj)%10,p-1); if((ii+jj+1)/10==1&&judge((ii+jj+1)%10,p-1)) ans+=dp(ii,jj,(ii+jj+1)%10,p-1); } } return ans; } char s[100]; int read(){ int len=strlen(s); char* p=find(s,s+len,'+'); *p=0; strcpy(a[0],s); char* p2=find(p+1,s+len,'='); *p2=0; strcpy(a[1],p+1); strcpy(c,p2+1); la[0] = strlen(a[0]); la[1] = strlen(a[1]); lc = strlen(c); rep(i,2) reverse(a[i],a[i]+la[i]); reverse(c,c+lc); return 1; } int main() { int kase=1; while(scanf("%s",s)==1){ read(); memset(d,-1,sizeof(d)); printf("Case %d: ",kase++); printf("%I64d\n",dp(0,0,0,lc)); } return 0; } /* 11??+??11=1111 ??+??=??? 111+???=111 ??+???=???? ???+???=?????? ??+11=111 */