【洛谷月赛十一月】 天选之人

很不错的一个构造题呢

更好的阅读体验

细节挺多的,大概在如下几点:

  1. 判断是 \(NO\) 的情况
  2. \(p = 0\) 的情况

现在我们来讨论一下,我们先让前\(P\)个人都是最大值所有者,我们计算一下他们的最大值:

	ll maxx = std::min(k / p,m);

我们依据我们算出的这个最大值来讨论:

\(p = 0\)时显然无解,因为必定会有最大值。

\(k = 0\)时,如果\(p != n\) 则无解。

如果剩下\(n - p\)个人都取他们能取到底最大值\(maxx - 1\)却仍不能将他们需要取完的\(k - maxx * p\) 则无解。

以上是无解的三种情况,我们接下来输出有解时非最大值人的答案:

	ll now = k - maxx * p;
	ll put = std::max(maxx - 1,(ll)0);
	for(int i = p + 1;i <= n;++i){
		ll should = std::min(now,put);
		std::cout<<should<<" "<<m - should<<std::endl;
		now -= should;
	}

\(now\)是当前是剩余的有标记的纸张数量,\(should\)是这个人所需要的答案,因为不能有负数,有标记的牌最多\(k\)张,所以进行一些大小比对。

喜闻乐见的代码环节:

// code by Dix_
#include<iostream>
#include<cstdio>
#define ll long long

ll n,m,k,p;

int main(){
	scanf("%lld%lld%lld%lld",&n,&m,&k,&p);
	if(p == 0){
		puts("NO");
		return 0;
	}
	if(k == 0 && p != n){
		puts("NO");
		return 0;
	}
	ll maxx = std::min(k / p,m);
	if((n - p) * (maxx - 1) < k - maxx * p){
		puts("NO");
		return 0;
	}
	puts("YES");
	for(int i = 1;i <= p;++i)
	std::cout<<maxx<<" "<<m - maxx<<std::endl;
	ll now = k - maxx * p;
	ll put = std::max(maxx - 1,(ll)0);
	for(int i = p + 1;i <= n;++i){
		ll should = std::min(now,put);
		std::cout<<should<<" "<<m - should<<std::endl;
		now -= should;
	}
}
posted @ 2020-11-28 20:21  fhq_treap  阅读(62)  评论(0编辑  收藏  举报