记dpl,r表示l,r这段数能形成的答案总和。
枚举最后一步操作k,如果是乘法,答案为dpl,k∗dpk+1,r,由于分配率这个会乘开来。如果是加法那么是dpl,r∗(r−k−1)!+dpk+1,r∗(k−l)!,即要乘上右边k+1,r这些数所有可行的方案数,减法同理。最后乘上(k−lr−l−2),即把两边操作合起来的方案数。
答案为dp1,n。
3 3 2 1 -+ 5 1 4 6 8 3 +*-*
2 999999689HintTwo numbers are considered different when they are in different positions.
/* *********************************************** Author :CKboss Created Time :2015年08月19日 星期三 21时58分12秒 File Name :HDOJ5396.cpp ************************************************ */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <cmath> #include <cstdlib> #include <vector> #include <queue> #include <set> #include <map> using namespace std; typedef long long int LL; const int maxn=210; const LL mod=1e9+7LL; int n; LL a[maxn]; char ope[maxn],cmd[maxn]; LL dp[maxn][maxn]; LL C[maxn][maxn]; LL jc[maxn]; void init() { jc[0]=1; C[0][0]=1LL; for(int i=1;i<maxn;i++) { C[i][i]=C[i][0]=1LL; jc[i]=(jc[i-1]*i)%mod; } for(int i=1;i<maxn;i++) { for(int j=1;j<i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; } } void DP() { memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) dp[i][i]=a[i]; for(int len=2;len<=n;len++) { for(int i=1;i+len-1<=n;i++) { int j=i+len-1; for(int k=i;k<j;k++) { int left=k-i; int right=len-2-left; LL t=0; if(ope[k]=='*') { t=(dp[i][k]*dp[k+1][j])%mod; } else if(ope[k]=='+') { t=(dp[i][k]*jc[right]%mod+dp[k+1][j]*jc[left]%mod)%mod; } else if(ope[k]=='-') { t=(dp[i][k]*jc[right]%mod-dp[k+1][j]*jc[left]%mod+mod)%mod; } dp[i][j]=(dp[i][j]+t*C[len-2][left]%mod)%mod; } } } } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); init(); while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) scanf("%lld",a+i); scanf("%s",cmd+1); for(int i=1;i<n;i++) ope[i]=cmd[i]; DP(); printf("%lld\n",dp[1][n]%mod); } return 0; }