/*
题目描述:给定一个形式如? + ? - ? + ? + ? = n的字符串,在每个?的位置填入1——n中的某一个数,使这个等式成立,
问这样的等式是否存在,如果存在,输出将?替换成具体数字后的字符串
思路:假设一共加了add个数,减掉了minus个数,那么这个算式能组合出的数的范围就是[ max(0 , add - n * minus) , add * n - minus],
如果n在这个范围内的话,则一定有解,然后二分出所有加上的数的总和ans1,所有减掉的数的总和ans2;每次遇到
加号的时候,就加上一个尽可能大的数(既不超过n,也不能因为加上了他而使得后面的加号后没有数可加),遇到
减号时同理,按照这个规则替换掉所有的?即可
*/
#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-6;
const int maxn = 1e4 + 5 ;
char s[maxn] ;
LL n , maxv , minv ;
LL add_max , add_min , minus_max , minus_min ;
int bsearch(int left , int right , int & ret ) //返回值为加上的所有数的总和ans1,参数ret为减去所有数的总和ans2
{
int mid ;
while(left <= right){
mid = left + (right - left) / 2 ;
if( mid - n < minus_min ){ //mid - n为需要减去的数的和,如果比能减去的数的最小值还要小,说明mid取小了
left = mid + 1 ;
}
else if( mid - n > minus_max){
right = mid - 1 ;
}
else{
ret = mid - n ;
return mid ;
}
}
}
int main()
{
char ch ;
int cnt = 0 ;
LL add = 0 , minuss = 0 ;
while(scanf("%c",&ch)== 1 && ch != '='){
if(ch == '+') ++add;
else if(ch == '-') ++minuss ;
s[cnt++] = ch ;
}
s[cnt] = 0;
scanf("%lld",&n);
++add ;
add_min = add , add_max = (LL)n * add , minus_min = minuss , minus_max = (LL)n * minuss ;
minv = max(add_min - minus_max , (LL)0 ) ;
maxv = add_max - minus_min ;
if(!(minv <= n && n <= maxv)){
printf("Impossible\n");
return 0;
}
printf("Possible\n");
int ans1 , ans2 ;
ans1 = bsearch(add_min , add_max , ans2) ;
int flag = 1 , len = strlen(s);
for(int i = 0 ; i< len ; i++){
if(s[i] == '?'){
if(flag){
LL res = min( n , ans1 - (add - 1 ) ) ; //对于每个加号,可以加上的最大的值为ans1
res = max( (LL)1 , res );
ans1 -= res ;
--add ;
printf("%lld",res) ;
}
else{
LL res = min( n , ans2 - (minuss - 1 ) ) ;
res = max( (LL)1 , res) ;
ans2 -= res ;
--minuss ;
printf("%lld",res) ;
}
continue ;
}
printf("%c",s[i]);
if(s[i] == '-') flag = 0;
else if(s[i] == '+') flag = 1 ;
}
printf("= %lld\n",n);
return 0;
}
codeforces round #347 div2 B rebus 贪心 + 二分
最新推荐文章于 2024-07-08 09:59:31 发布