洛谷月赛 P7107 天选之人

AC传送门!

题目大意

对于两个序列 (x_i, y_i), 使得他们满足下列条件:

  1. (x_i, y_i ge 0, x_i + y_i = m)
  2. (sumlimits^{n}_{i=1}x_i = k)
  3. 有且仅有 (p) 个互不相同的 (j) 使 (x_j = maxlimits^n_{i-1} {x_i})

Solution:

直接贪心即可。首先直接 (k / p) 作为前 (p) 个的最大值,可以证明这样一定不会更劣。当然,这里也可以利用二分来判断答案是否合法,从而得到一个合法解,但没有必要。

接着,考虑如何输出剩下的解。首先,我们要保证剩下的所有 (x) 一定要小于 (k / p),所以考虑部分答案设为 (k / p - 1), 那么不断将 (k) 减去该值,如果小于,则输出不整的那一剩下部分,最后全部输出 (0) 即可。

代码:

#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define int long long

template <class T>  
inline void read(T& a){
    T x = 0, s = 1;
    char c = getchar();
    while(!isdigit(c)){
        if(c == '-') s = -1;
        c = getchar(); 
    }
    while(isdigit(c)){
        x = x * 10 + (c ^ '0');
        c = getchar(); 
    }
    a = x * s;
    return ; 
}

int n, m, k, p; 


signed main(){
        read(n), read(m), read(k), read(p);
        int pin = k / p;
	if(pin > m) pin = m;   // 平均值 
	if((n - p) * (pin - 1) < (k - pin * p) || (k == 0 && p != n)){
		printf("no");
		return 0; 
	}
	if(n == p && (double)n / p != n / p){
		printf("no
");
		return 0; 
	}
	printf("yes
");
	for(int i = 1; i <= p; i++)
		printf("%lld %lld
", pin, m - pin);
	int cnt = 0;
	k -= p * pin; 
	while(k >= pin && cnt < n - p){
		printf("%lld %lld
", pin - 1, m - pin + 1);
		k -= pin - 1; 
		cnt++; 
	}
	if(k != 0){
		printf("%lld %lld
", k, m - k);
		cnt++; 
	}
	for(int i = 1; i <= n - p - cnt; i++)
		printf("0 %lld
", m); 
	return 0;
}
原文地址:https://www.cnblogs.com/wondering-world/p/14054191.html