本题目,一些位置给了一个 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
*/