C*++ language is quite similar to C++. The similarity manifests itself in the fact that the programs written in C*++ sometimes behave unpredictably and lead to absolutely unexpected effects. For example, let’s imagine an arithmetic expression in C*++ that looks like this (expression is the main term):
expression ::= summand | expression + summand | expression - summand
summand ::= increment | coefficientincrement
increment ::= a++ | ++a
coefficient ::= 0|1|2|…|1000
For example, "5a+±3*++a+a++" is a valid expression in C*++.
Thus, we have a sum consisting of several summands divided by signs “+” or “-”. Every summand is an expression “a++” or “++a” multiplied by some integer coefficient. If the coefficient is omitted, it is suggested being equal to 1.
The calculation of such sum in C*++ goes the following way. First all the summands are calculated one after another, then they are summed by the usual arithmetic rules. If the summand contains “a++”, then during the calculation first the value of the “a” variable is multiplied by the coefficient, then value of “a” is increased by 1. If the summand contains “++a”, then the actions on it are performed in the reverse order: first “a” is increased by 1, then — multiplied by the coefficient.
The summands may be calculated in any order, that’s why sometimes the result of the calculation is completely unpredictable! Your task is to find its largest possible value.
Input
The first input line contains an integer a ( - 1000 ≤ a ≤ 1000) — the initial value of the variable “a”. The next line contains an expression in C*++ language of the described type. The number of the summands in the expression does not exceed 1000. It is guaranteed that the line describing the expression contains no spaces and tabulation.
Output
Output a single number — the maximal possible value of the expression.
题意:表达式求解,和正常的运算不同的是可以选择每个被加数的运算顺序,询问最大的值是多少。
一开始想的是区间dp,枚举每个区间内最后一个被选择的a是哪个,思路应该没有问题,但是数据范围太大,区间dp搞一搞要超时,所以就放弃了dp的思路。
其实只要考虑4个式子就好,k*++a+ma++,k++a+m*++a,ka+++ma++,ka+++m++a,先算第一个再算第二个,先算第二个再算第一个,最后发现选择a计算的顺序和a的值并没有关系,只和系数有关,想让值最大,应该是按照从系数从小到大的顺序选择,在纸上一算就就能得出这个结论了。两个a顺序的顺序确定,那么n个数字的顺序也就确定了,按照系数从小到大的顺序计算能够得出正确答案。
以k*++a+ma++举个例子,先计算第一个a再算第二个,sum=k(a+1)+m*(a+1),先计算第二个再算第一个,sum=k(a+2)+m*a,两式相减得m-k,可知想让第一种选法值更大,m需要大于k,即选择更小的系数,并且顺序和a无关。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
#define maxn 1010
struct node
{
int co;//系数
int key;//判断是a++还是++a
} num[maxn];
int seven;//判读有无负号
char str[maxn*100];
int init;
bool cmp(node x,node y)
{
return x.co<y.co;
}
int main()
{
scanf("%d",&init);
scanf("%s",str);
seven=1;
int cnt=1;
int length=strlen(str);
int now=0;
int pre=-1;//上一个a可以达到的范围
for(int i=1; i<=1000; i++)
num[i].co=1;//初始化系数为1
while(now<length)
{
if(str[now]=='-')
{
seven=-1;
now++;
}
else if(str[now]=='*'||str[now]=='+')
now++;
else if(str[now]=='a')
{
if(now-2>pre&&str[now-1]=='+'&&str[now-2]=='+')//说明为++a
{
pre=now;//那么这一项能覆盖的位最多到现在的a,下面的pre同理
num[cnt].co*=seven;
num[cnt].key=0;
cnt++;
now++;
}
else
{
pre=now+2;
num[cnt].co*=seven;
num[cnt].key=1;
cnt++;
now+=3;
}
seven=1;
}
else
{
int sum=0;
while(str[now]>='0'&&str[now]<='9')
{
sum=sum*10+(str[now]-'0');
now++;
}
num[cnt].co=sum;
}
}
cnt--;
sort(num+1,num+1+cnt,cmp);
int ans=0;
for(int i=1; i<=cnt; i++)
{
if(!num[i].key)
{
init++;
ans+=(num[i].co*init);
}
else
{
ans+=(num[i].co*init);
init++;
}
}
printf("%d\n",ans);
return 0;
}
该博客讨论了如何在C*++语言中计算带有变量a的数学表达式,其中a++和++a的顺序影响结果。博主提出,为了获得最大值,应当根据系数大小来决定a的计算顺序,而与a本身初始值无关。博主通过举例说明了如何按照系数从小到大的顺序计算,以确保结果最大化,并指出这种策略适用于所有此类表达式。
594

被折叠的 条评论
为什么被折叠?



