2015暑假多校联合---Expression(区间DP)

本文介绍了一种使用区间动态规划解决运算符优先级问题的方法,通过给定的数值和运算符序列,计算所有可能运算顺序的结果之和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

http://acm.split.hdu.edu.cn/showproblem.php?pid=5396

 

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
 
Hint
Two numbers are considered different when they are in different positions.
 
Author
xudyh
 
Source
 
Recommend
wange2014   |   We have carefully selected several similar problems for you:   5867  5866  5865  5864  5863 
 
题意:输入n个数,n-1个运算符(只有“+”、“—”、“*”),组成一个算式,给这n-1个运算符赋予不同的运算优先级(运算先后次序),每次得到一个值,求在所有值的和;
 
思路:区间DP,对于区间[i,j] 分为[i,k] 和[k+1,j]   设[i,k]在不同运算次序下的所有值为X1、X2、X3....Xn  那么dp[i][k]=(X1+X2+X3+...+Xn)   
        同样设dp[k+1][j]=(Y1+Y2+Y3+....+Ym)     如果第k个运算符为“*”  dp[i][j]=X1*(Y1+...+Ym)+...+Xn*(Y1+...+Ym) =dp[i][k]*dp[k+1][j];
        如果不是“*”    dp[i][j]=dp[i][k]*A[j-1-k]+dp[k+1][j]*A[k-i]    A[]表示排列,为什么要乘以排列数呢? 分析可知,对于区间[i,k]中的一个值对应区间[k+1][j]的所有         值,而后面区间中由运算符优先级得到的值的个数就是后面区间的运算符个数的排列数;
        最后要乘上组合数,对于区间[i,j]分为[i,k] [k+1,j]的贡献次数是C[j-i][k-i] 为什么呢?  因为前后两个区间的运算优先级对彼此没有影响;
 
代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#define eps 1e-8
#define maxn 105
#define inf 0x3f3f3f3f3f3f3f3f
#define IN freopen("in.txt","r",stdin);
using namespace std;
const long long mod=1e9+7;
long long a[105];
char s[105];
long long dp[105][105];
long long A[120];
long long C[120][120];

int main()
{
    int n;
    A[0]=1;
    for(long long i=1;i<=110;i++)  ///排列数;
        A[i]=A[i-1]*i%mod;

    for(int i=0;i<110;i++)         ///组合数;
        C[i][0]=1;
    C[1][1]=1;
    for(int i=1;i<110;i++)
    {
        for(int j=1;j<=i;j++)
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    }
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        scanf("%s",s+1);
        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<=n;i++)
            {
                if(i+len-1>n) break;
                for(int k=i;k<i+len-1;k++)
                {
                    long long t;
                    if(s[k]=='*')
                        t=(dp[i][k]*dp[k+1][i+len-1])%mod;
                    else if(s[k]=='-')
                        t=(dp[i][k]*A[i+len-2-k]-dp[k+1][i+len-1]*A[k-i])%mod;
                    else
                        t=(dp[i][k]*A[i+len-2-k]+dp[k+1][i+len-1]*A[k-i])%mod;
                    dp[i][i+len-1]=(dp[i][i+len-1]+t*C[len-2][k-i])%mod;
                }
            }
        }
        printf("%lld\n",(dp[1][n]%mod+mod)%mod);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/chen9510/p/5831135.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值