题目链接:
CF #347 (Div.2) B. Rebus
题意:
给一串只含加号和减号的运算式,以及运算结果为n,运算数全是’?’,问能否用不大于n的正整数代替所有的’?’,使得等式成立?如果能任意输出一种构造方式。
分析:
设所有’?’的个数是
num
个,减号的个数是
negative
个,那么可以用不大于n的正整数代替所有的’?’能表示的数据范围是:
low=num-negative-negative*n;//所有正数全用1代替,所有负数全用-n代替
high=(num-negative)*n-negative;//所有正数全用n代替,所有负数全用-1代替
只有当n属于集合
[low,high]
时,才能构造出等式。
构造等式可以先令所有的正数全是1,所有的负数全是-1,那么构造成n还需要的数是:
total=n+negative−(num−negative);
注意total可正可负!本菜就是在比赛时只考虑了total为正数的情况,所以终判时gg了。o(╯□╰)o,一大早上起来,目瞪口呆.jpeg。
当
n−1≤total
时将那么就可以把一个正数增加到n,然后total减去n-1;
当
0<total<n−1
时可以把一个正数增加到total+1,然后total=0;
当
total≤−(n−1)
时可以把一个负数减少到-n然后total增加n-1;
当
−(n−1)<total<0
时可以把一个负数减少的-(total+1),然后total=0;
当total=0时,那么剩下的所有正数就全是1,所有的负数全是-1.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cmath>
using namespace std;
const int maxn=1100;
char s[maxn];
int main()
{
//freopen("Bin.txt","r",stdin);
gets(s);
int len=strlen(s);
int n,num,negative;
n=num=negative=0;
for(int i=0;i<len;i++){
if(s[i]=='?') num++;
else if(s[i]=='-') negative++;
else if(s[i]>='0'&&s[i]<='9') {
n=n*10+s[i]-'0';
}
}
int high=(num-negative)*n-negative;
int low=num-negative-negative*n;
//printf("low=%d high=%d\n",low,high);
if(n<low||n>high) printf("Impossible\n");
else {
int total=n+negaitive*2-num; //total可正可负!!!
printf("Possible\n");
int pre=0; //pre用以标记是'+'还是'-'
for(int i=0;i<len;i++){
if(s[i]=='?'){
int base=1;
if(pre==0&&total>0){ //考虑当前正数
if(total>=n-1){
total-=(n-1);
base=n;
}else {
base+=total;
total=0;
}
}else if(pre==1&&total<0){ //考虑当前负数
if(total<=-(n-1)){
total+=(n-1);
base=n;
}else {
base-=total;
total=0;
}
}
printf("%d",base);
}else {
printf("%c",s[i]);
if(s[i]=='+') pre=0;
else if(s[i]=='-') pre=1;
}
}
printf("\n");
}
return 0;
}