题目1 : 等式填空
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
??+?=23
样例输出
-
9
-
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e9+7; char s[105],*sum; int dis[105][2],num,i,len; ll f[105][505],dp[55][55][505]; void init() { dp[0][0][0]=1; for(int i=0;i<55;i++) for(int j=0;j<55;j++) for(int k=0;k<505;k++) { if(i) for(int ii=0;ii<10&&k>=ii;ii++) dp[i][j][k]+=dp[i-1][j][k-ii]; if(j) for(int ii=1;ii<10&&k>=ii;ii++) dp[i][j][k]+=dp[i][j-1][k-ii]; if(i&&j) for(int ii=1;ii<19&&k>=ii;ii++) dp[i][j][k]-=dp[i-1][j-1][k-ii]*min(ii,19-ii); dp[i][j][k]=(dp[i][j][k]%mod+mod)%mod; } } ll dfs(int now,int last) { if(now==len) return last==0&&(!(dis[now][0]||dis[now][1])); if(f[now][last]!=-1) return f[now][last]; ll res=0; int now_state=(sum[len-1-now]-'0'+10-last%10)%10; for(int i=now_state;i<505;i+=10) res=(res+dp[dis[now][0]][dis[now][1]][i]*dfs(now+1,(i+last)/10)%mod)%mod; return f[now][last]=res; } int main() { init(); while(scanf("%s",s)!=EOF) { num=0; memset(dis,0,sizeof(dis)); memset(f,-1,sizeof(f)); for(i=0;s[i];i++) if(s[i]=='?') dis[num++][0]++; else { dis[num-1][0]--; dis[num-1][1]++; num=0; if(s[i]=='=') break; } sum=s+i+1; len=strlen(sum); printf("%lld\n",dfs(0,0)); } return 0; }
描述
给定一个等式S,满足:
1. S中包含唯一的等号('=')
2. 等号右边是一个确定的非负整数
3. 等号左边是由'+'和'?'组成的算式,其中处于某个整数(即便这个整数只有一位)首位的'?'可以填入1-9中的某个数字,其余'?'可以填入0-9中的某个数字。
问有多少种不同的填法使等式成立? 由于答案可能非常大,你只需输出结果模1000000007的余数。
例如对于如下等式:
??+??=23
一共有10+13=23, 11+12=23, 12+11=23, 13+10=23, 4种不同的填法。
输入
一行字符串,代表等式S。
对于40%的数据,等号右边的整数小于等于100000。
对于100%的数据,S长度不超过100。
输出
输出不同填法的数目。由于答案可能非常大,你只需输出结果模1000000007的余数。