hdu5396 Expression

Problem Description
Teacher Mai has n numbers a1,a2,,anand n1 operators("+", "-" or "*")op1,op2,,opn1, which are arranged in the form a1 op1 a2 op2 a3  an.

He wants to erase numbers one by one. In i-th round, there are n+1i numbers remained. He can erase two adjacent numbers and the operator between them, and then put a new number (derived from this one operation) in this position. After n1 rounds, there is the only one number remained. The result of this sequence of operations is the last number remained.


He wants to know the sum of results of all different sequences of operations. Two sequences of operations are considered different if and only if in one round he chooses different numbers.

For example, a possible sequence of operations for "1+4683" is 1+46831+4(2)31+(8)3(7)321.
 

Input
There are multiple test cases.

For each test case, the first line contains one number n(2n100).

The second line contains n integers a1,a2,,an(0ai109).

The third line contains a string with length n1 consisting "+","-" and "*", which represents the operator sequence.
 

Output
For each test case print the answer modulo 109+7.
 

Sample Input
3 3 2 1 -+ 5 1 4 6 8 3 +*-*
 

Sample Output
2

999999689

这题是一道很好的区间dp,看完解题报告后才会做,先用状态dp[i][j]表示区间[i,j]里的和,用A[i]表示1到i的阶乘,c[i][j]表示组合数。那么我们在区间[i,j]里枚举k,(i<=k<j),如果当前第k个是乘号,那么根据乘法分配律,t=(dp[i][k]*dp[k+1][j])%MOD;,如果当前第k个是加或减,那么t=dp[i][k]*t=(dp[i][k]*A[j-k-1]+dp[k+1][j]*A[k-i])%MOD;因为选择的这个加号或减号两端的运算是互不干扰的,而一边的运算次数为另一边的组合数,所以有这样的状态方程,另外还要乘上一个c[j-i-1][k-i],因为我们确定的是两边各自的运算,但是我们可以这样的顺序取:左边先算乘法,然后右边算加法,再左边算减法...相当于安排左边符号运算在总运算个数的次序。还有注意(a+MOD)%MOD要在最后才能用,前面不能用,只能用a%MOD,不然会使结果改变。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
#define ll long long
#define MOD 1000000007
char s[106];
ll a[106],dp[106][106],A[106],c[106][106];
void init()
{
    int i,j;
    A[0]=1;
    A[1]=1;
    A[2]=2;
    for(i=3;i<=100;i++){
        A[i]=(A[i-1]*(ll)i)%MOD;
    }
    for(i=1;i<=100;i++)c[i][0]=1;

    for(i=1;i<=100;i++){
        for(j=1;j<=i;j++){
            if(i==j)c[i][j]=1;
            else if(i>j)
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;
        }
    }
}

int main()
{
    int n,m,i,j,T,len,k;
    ll t;
    init();
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            dp[i][i]=a[i];
        }
        scanf("%s",s+1);
        for(i=1;i<=n-1;i++){
            if(s[i]=='+'){
                dp[i][i+1]=(a[i]+a[i+1])%MOD;
            }
            else if(s[i]=='-'){
                dp[i][i+1]=(a[i]-a[i+1])%MOD;
            }
            else if(s[i]=='*')
                dp[i][i+1]=(a[i]*a[i+1])%MOD;   /*!!!!!!!!!!!!!!!!!*/
        }
        for(len=3;len<=n;len++){
            for(i=1;i+len-1<=n;i++){
                j=i+len-1;
                dp[i][j]=0;
                for(k=i;k<j;k++){
                    t=0;
                    if(s[k]=='*'){
                        t=(dp[i][k]*dp[k+1][j])%MOD;
                    }
                    else if(s[k]=='+'){
                        t=(dp[i][k]*A[j-k-1]+dp[k+1][j]*A[k-i])%MOD;

                    }
                    else if(s[k]=='-'){
                        t=(dp[i][k]*A[j-k-1]-dp[k+1][j]*A[k-i])%MOD;
                    }
                    dp[i][j]=(dp[i][j]+t*c[j-i-1][k-i])%MOD;
                }

            }
        }
        printf("%lld\n",(dp[1][n]+MOD)%MOD);
    }
    return 0;
}


posted @ 2015-09-10 20:27  Herumw  阅读(110)  评论(0编辑  收藏  举报