hdu 5396 Expression 区间DP+排列组合 2015 Multi-University Training Contest 9

来源:互联网 发布:服装生产库存软件 编辑:程序博客网 时间:2024/06/05 18:57

Expression

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 453    Accepted Submission(s): 264


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
33 2 1-+51 4 6 8 3+*-*
 

Sample Output
2999999689
Hint
Two numbers are considered different when they are in different positions.
 

Author
xudyh
 

Source
2015 Multi-University Training Contest 9
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5405 5404 5403 5402 5401 


区间DP,
dp[i][j]表示区间[i,j]所有可能的计算顺序之后结果的和。

考虑区间i,j最后一个计算的符号位置:设符号左边所有可能的计算顺序之后结果有a1,a2,...,an,右边可能的结果有b1,b2,b3,...,bn。(可重)

计算方法:首先将所有ai 根据最后一个符号和所有bi,+或-或*,然后再对其排列,因为每种ai (+或-或*) bi
左区间和右区间内的符号运行相对顺序可以不同,但是结果相同。
(左右区间自身的顺序是定的,因为用dp之前已算出子区间所有顺序的结果和)

'+':
dp[i][j]=C (组合公式) *  ( ∑ai * A( 右区间符号数全排列)   + ∑bi *A(左区间符号数全排列)  )
      (左右区间的相对顺序) ( 对于每个ai,一共加了A( 右区间符号数全排列)多次。)

dp[i][j]=(dp[i][k-1]*A( 右区间符号数全排列)+dp[k][i]*A(左区间符号数全排列))*C( , );      (k=i+1,...,j);

'-':dp[i][j]=(dp[i][k-1]*A( 右区间符号数全排列)-dp[k][i]*A(左区间符号数全排列))*C( , ); 

'*'::dp[i][j]=(dp[i][k-1]*dp[k][i])*C( , ); 

d[i][j]=C( ,)  *(a1*b1+a1*b2+...+a1*bn+a2*b1+...an*bn)=C( ,)  *ai*∑bi



#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<climits>#include<queue>#include<vector>#include<map>#include<sstream>#include<set>#include<stack>#include<utility>#pragma comment(linker, "/STACK:102400000,102400000")#define PI 3.1415926535897932384626#define eps 1e-10#define sqr(x) ((x)*(x))#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)#define  lson   num<<1,le,mid#define rson    num<<1|1,mid+1,ri#define MID   int mid=(le+ri)>>1#define zero(x)((x>0? x:-x)<1e-15)#define mp    make_pair#define _f     first#define _s     secondusing namespace std;const int INF =0x3f3f3f3f;const int maxn= 100+5   ;//const int INF=    ;typedef long long ll;const ll mod= 1000000000+7    ;const ll inf =1000000000000000;//1e15;//ifstream fin("input.txt");//ofstream fout("output.txt");//fin.close();//fout.close();//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);//by yskysker123


 
int n;int a[maxn];char c[maxn];ll dp[maxn][maxn];ll A[maxn];ll C[maxn][maxn];<span style="font-family: 'Times New Roman';">  //杨辉三角预处理全排列和组合结果</span>void pre(){    A[0]=1;    for(ll i=0;i<maxn;i++)       //C(0,x),C( x,0)的情况不能漏,这里可以视为1              {       if(i>0) A[i]=A[i-1]*i%mod;        for(ll j=0;j<=i;j++)                                {            if(j==0||j==i)  C[i][j]=1;                          else            {                C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;             }        }    }}int main(){    pre();    while(~scanf("%d",&n))    {        FOR0(i,n)        scanf("%d",&a[i]);        FOR1(i,n-1)        scanf(" %c",&c[i]);        memset(dp,0,sizeof dp);        for(int i=0;i<=n-1;i++)        {            dp[i][i]=a[i];        }        for(int j=0;j<=n-1;j++)  //计算的顺序        {            for(int i=j-1;i>=0;i--)            {                ll ret;                for(int k=i+1;k<=j;k++)                {                    if(c[k]=='*')                    {                        ret= (dp[i][k-1] * dp[k][j])%mod;                    }                    else if(c[k]=='+')                    {                        ret=(dp[i][k-1]*A[j-k  ]%mod +dp[k][j]*A[k-1-i]%mod )%mod;                    }                    else                    {                        ret=((dp[i][k-1]*A[j-k  ]%mod -dp[k][j]*A[k-1-i]%mod )+mod)%mod;                    }                    ret=ret*C[j-i-1][k-i-1 ]%mod;                     dp[i][j]=(dp[i][j]+ret)%mod;                }            }        }        printf("%lld\n",dp[0][n-1]);    }    return 0;}




本题用以下的组合公式不仅超时,而且是错的,因为取了模。
//ll C(ll n,ll m)//{//    ll ans=1;//    m=min(m,n-m);//    for(ll i=1;i<=m;i++)//    {//        ans=ans*(n-i+1)/i   %mod;////    }////    return ans;////}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 两个月宝宝不拉屎只放屁怎么办 两个月大宝宝两天没拉屎怎么办 两个月宝宝三天没拉大便怎么办 5个月宝宝3天没拉大便怎么办 4个月宝宝3天没拉大便怎么办 20个月的宝宝大便干燥怎么办 20个月宝宝大便间隔三天怎么办 两个多月的宝宝四天没大便怎么办 两个多月的宝宝几天没大便怎么办 2个月3天没大便怎么办 两个月大的宝宝发烧40度怎么办 两个月大的宝宝感冒了怎么办 四个月宝宝拉水样大便要怎么办 六个月的宝宝咳嗽有痰怎么办 未满月的宝宝大便脓状怎么办 五个月的宝宝总是吃手怎么办 小孩子学数字怎么也学不会怎么办 小孩学数字老是学不会该怎么办 只买了大人票忘买儿童的了怎么办 铝合金滑动门没轨道安纱门怎么办 移门衣柜门与柜体有冶缝隙怎么办 推拉门关门时撞门框声音大怎么办 两岁宝宝夏天不盖被子怎么办 家里有好多会爬的小黑虫怎么办 刚贴的壁纸怎么发霉了怎么办 晚上睡觉一熄灯有许多小虫子怎么办 一岁宝宝夏天爱哭不爱吃饭怎么办 合肥房子卖了户口没地方迁怎么办 忌作灶的日子新房装橱柜了怎么办 刮水泥浆的墙面刮不住腻子怎么办 小学二年级孩子偷钱 老师怎么办 发现自己读初中的儿子偷钱怎么办? 做错事了得不到亲人的原谅怎么办? 窗口 窗套与墙缝隙大怎么办 中班小孩还不会认1到10怎么办 母猫奶头被小猫咬伤了怎么办 口红不小心弄到衣服上怎么办 脖子后背疼的睡不着觉应该怎么办 君子兰用高锰酸钾泡浓度高了怎么办 五个月宝宝认人不要奶奶睡怎么办 幼儿小班安全卡鱼刺了怎么办教案