Codeforce Round #437 div2 A B C E 题解


A:Between the Offices

题意:给出只含SF的字符串,S代表在S地,F代表在F地

若S-F的航班数多于F-S的航班数输出YES,否则输出NO

思路:考虑头尾,F开头肯定NO,S开头S结尾也是NO 其余都是YES


BSave the problem!

题意:给出问题A的答案D,请构造其中一种数据,

问题A:给出N种,面值不同,数目无限的硬币,求组成总价M的组合数D

面值的数目不同视为不同情况

思路:只需1 2的硬币就可以构造所有的D

由母函数,1元可以表示成:A1(m)=(1+x+x^2+x^3+x^4...x^m)

由母函数,2元可以表示成:A2(m)=(1+x^2+x^4+x^6.....x^m)

D就等于 1元和2元的卷积,指数为M的系数 

现在考虑比较简单的情况。。

M=2  ,A1(2)*A2(2)=1+x+2x^2+x^3+x^4

M=3          = 1+x+2x^2+2x^3+x^4+x^5

M=4    1+x+2x^2+2x^3+3x^4+2x^5+2x^6+x^7+x^8

对于出现的最高系数

M=2或3 D=2 

M=4或5 D=3

所以对于每一个D 我们输出M=2D-1 N=2  \n1 2就好了

对于D=1特判


C:Ordering Pizza

题意:有两种pizza:AB,AB都能分成s小块,共N个人每个人要吃Si块 

每吃一块A的小块+Ai开心值  B的小块+Bi开心值  

买尽量少的pizza但是要尽量开心值最大,问最大的开心值是多少

思路:多出来的A小块需要转成B (A->B) 或者 多出来的B小块需要转成A  

比较两者,开心值减少的小,就选哪个

ans=理论开心最大值-因转化损失的开心值

那么输入的时候把ai>bi的划入A->B的集合

ai<bi的划入B->A的集合

考虑贪心,对于A->B 尽量让Ai-Bi小的去转 ,排序

对于B->A 尽量让Bi-Ai小的去转

学到了个小技巧:如果si的和不是s的倍数,建一个虚拟人吃余数块但不加开心


E. Buy Low Sell High

题意:N天的股票价格,买卖不限,持有股票不限,但没有股票不能卖,问最大收益

思路:建一个multiset不断加入股价,如果今天的价格比队首低,删掉队首元素,加入两次今天的价格,

其中一次代表队首的股票升值成今天的股价,那么我们就可以赚差价


=========w========

AC code:

A:

int main()
{
	int n;
	cin>>n;
	getchar();
	char cs[105];
	for(int i=1;i<=n;i++)
	{
		char c;
		cin>>cs[i];
	} 
	if(cs[1]=='F')
	{
		printf("NO\n");
		return 0;
	}
	if(cs[1]=='S'&&cs[n]=='S')
	{
		printf("NO\n");
		return 0;
	}
	printf("YES\n");
	return 0;
}

B:

int main()
{ 
	int n;
	cin>>n;
	if(n==1)
	{
		printf("1 1\n");
		printf("1\n");
		return 0;
	}
		printf("%d 2\n",2*n-1);
		printf("1 2\n");
	return 0;
}

C:

#define ll long long
const int N =1e6+5;
ll a[N];
ll b[N];
ll eat[N];//每个人吃的数目
vector<pair<ll,ll> >atob,btoa;
int main()
{
	ll n,s;
	scanf("%I64d%I64d",&n,&s);
	ll sum=0;//小块总数目
	for(int i=0; i<n; i++)
	{
		scanf("%I64d%I64d%I64d",&eat[i],&a[i],&b[i]);
		sum+=eat[i];
	}
	ll nump=ceil((double)sum/s);// 要买多少份pizza
	ll extra=nump*s-sum;		//多出来的小块数
	eat[n]=extra;
	a[n]=0;
	b[n]=0;
	//计算理论最大值
	ll ans=0;
	ll cnta=0;
	ll cntb=0;
	for(int i=0; i<=n; i++)
	{
		if(a[i]>b[i])
		{
			ans+=a[i]*eat[i];
			atob.push_back(make_pair(a[i]-b[i],eat[i]) );
			cnta+=eat[i];
		}
		else
		{
			ans+=b[i]*eat[i];
			btoa.push_back(make_pair(b[i]-a[i],eat[i]) );
			cntb+=eat[i];
		}
	}
	//计算亏损 A-B or B-A
	ll lost=1e18;
	//A-B
	sort(atob.begin(),atob.end());
	ll tmp=0;
	ll extraa= cnta%s;//不能凑齐一份的A
	for(int i=0; i<(int)atob.size(); i++)
	{
		
		pair<ll,ll>p=atob[i];
		ll take=min(extraa,p.second);
		tmp+=take*p.first;
		extraa-=take;
	}
	lost=min(lost,tmp);
	
	//B-A
	tmp=0;
	sort(btoa.begin(),btoa.end());
	ll extrab=cntb%s;
	for(int i=0; i<(int)btoa.size(); i++)
	{
		
		pair<ll,ll>p=btoa[i];
		ll take=min(extrab,p.second);
		tmp+=take*p.first;
		extrab-=take;
	}
	lost=min(lost,tmp);
	
	ans-=lost;
	cout<<ans<<endl;
}

E:

#define ll long long
int n,w;
ll s;
multiset<int> hs;
int main()
{
	scanf("%d",&n);
	for(int i=0; i<n; i++)
	{
		scanf("%d",&w);
		hs.insert(w);
		hs.insert(w);
		hs.erase(hs.begin());
		s-=w;
	}
	for (multiset<int>::iterator poi=hs.begin();poi!=hs.end();poi++) 
	s+=*poi;
	printf("%lld\n",s);
}
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值