7+1?=1? ?1+?1=22
Case 1: 3 Case 2: 1
题意:给一个包含'?'的等式,问这个等式可能有多少种
题解:dp[i][0]代表第i位满足条件且不进位的方法数,dp[i][1]代表第i位满足条件且进位的方法数。
然后枚举每个'?'可能的值,值的范围(以a为例)起点:a[i]=='?' 是 i不是最高位或者a只有个位 ?1:0
否 a[i]
终点:a[i]=='?' 是 9
否 a[i]
其他的就是各种判断了。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define LL long long LL dp[15][2];//dp[i][0]代表第i位满足条件且不进位的方法数,dp[i][1]代表第i位满足条件且进位的方法数 int a[15],b[15],c[15]; char s[50]; int al,bl,cl; int main() { for(int l,cas=1;~scanf("%s",s);++cas) { al=bl=cl=0; memset(dp,0,sizeof(dp)); //下面的清零很重要啊,因为这个一直WA... memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); for(l=0;s[l]!='+';++l) { if(s[l]=='?') a[al++]=-1; else a[al++]=s[l]-'0'; } for(l=l+1;s[l]!='=';++l) { if(s[l]=='?') b[bl++]=-1; else b[bl++]=s[l]-'0'; } for(l=l+1;l<strlen(s);++l) { if(s[l]=='?') c[cl++]=-1; else c[cl++]=s[l]-'0'; } //a,b有一个的数字长度大于c if(cl<bl||cl<al) { printf("Case %d: 0\n",cas); continue; } reverse(a,a+al); reverse(b,b+bl); reverse(c,c+cl); for(int i=0;i<cl;++i) for(int j=(a[i]<0?((i<al-1||al==1)?0:1):(a[i]));j<=(a[i]<0?9:a[i]);++j) for(int k=(b[i]<0?((i<bl-1||bl==1)?0:1):(b[i]));k<=(b[i]<0?9:b[i]);++k) { LL add; if((c[i]<0||((j+k+1)%10==c[i]))) //上一位进位的情况 { add=(i>0?dp[i-1][1]:0); if(j+k+1>=10) dp[i][1]+=add; else dp[i][0]+=add; } if((c[i]<0&&(i!=cl-1))||(c[i]<0&&(i==cl-1)&&(j+k>0))||(cl==1&&c[i]<0)||((j+k)%10==c[i])) //上一位没有进位的情况 { add=(i>0?dp[i-1][0]:1); if(j+k>=10) dp[i][1]+=add; else dp[i][0]+=add; } } printf("Case %d: %I64d\n",cas,dp[cl-1][0]); } return 0; }