2020牛客寒假算法基础集训营4 E 最小表达式

题目传送门

题目描述

给出一个包含数字1-9和加号的字符串,请你将字符串中的字符任意排列,但每种字符数目不变,使得结果是一个合法的表达式,而且表达式的值最小。输出那个最小表达式的值
合法的表达式的定义如下:

  • 一个数字,如233,是一个合法的表达式
  • A + B是合法的表达式,当且仅当 A , B 都是合法的表达式
    保证给出的表达式经过重排,存在一个合法的解。

输入描述:

一行输入一个字符串,仅包含数字1-9和加号+。
字符串的长度小于500000。

输出描述:

一行输出一个数字,代表最小的解。

示例1

输入

111+1

输出

22

说明

11+11=22

示例2

输入

23984692+238752+2+34+

输出

5461

说明

嗯,这个答案是可以得到的

备注:
注意,答案长度可能长达500000个字符。

这个题怎么说呢,其实是挺简单的一道题,统计一下有k个加号,不是加号的字符用一个数组a存起来,则一共分为k+1个数加起来的和,根据贪心的原则,大的数在后面,我刚开始想的是先对数组a进行排序,然后每个数的位置对k+1取模相等的数组成一个数,然后就能得到k个数,这样想其实是没问题的,但是这样写会爆掉。上一下我开始提交的代码

#include<bits/stdc++.h>
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
const int mod = 998244353;
const int MAXN = 1e6 + 10;
const int INF = 0x3f3f3f3f;
LL res=1,n,k,Max,now,m,sum=0,c;
string st[MAXN];
int a[MAXN];
int main()
{
    string str;
    cin>>str;
    int len=str.size();
    for(int i=0;i<str.size();i++)
    {
        if(str[i]=='+')k++;
        else a[now++]=str[i]-'0';
    }
    sort(a,a+now);
    for(int i=0;i<=k;i++)
    {   
        res=0;
        for(int j=i;j<now;j+=(k+1))
        {
            res=res*10+(a[j]);
        }
        //cout<<res<<endl;
        sum+=res;
    }
    cout<<sum<<endl;
     
}

明显这里必须的用数组存,后来想想发现,是把每一位上的和加起来,存到数组里,有进位的话要进位,哎,自己真的太菜了!
AC代码

#include<bits/stdc++.h>
#define N 1010000
#define MS0(X) memset((X), 0, sizeof((X)))
typedef long long ll;
typedef unsigned long long ull;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
using namespace std;
int a[N],b[N],jw,arr[N],h;
char s[N];
int now,k;
int main()
{
	string str;
	cin>>str;
	for(int i=0;i<str.size();i++)
	{
		if(str[i]=='+')k++;//统计等号个数,分成k+1个数
		else s[now++]=str[i];
	}
	sort(s,s+now);
	for(int i=now-1;i>=0;i=i-k-1)
	{
		int ans=0;
		for(int j=i;j>=i-k&&j>=0;j--)
		ans=ans+s[j]-'0';//对每一位上的数进行相加
		
		ans+=jw;//当前位的数需要加上来自前一位的进位
		arr[h++]=ans%10;//当前位的数位ans对10取模
		jw=ans/10;、、向下一位进位
		
	}
	if(jw>0)arr[h++]=jw;//进位
	for(int i=h-1;i>=0;i--)//倒着输出
	cout<<arr[i];
	cout<<endl;
}
 

感谢爸爸们的访问,你们的访问时我不断进步的动力!

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值