2018-7-8 ACM 刷题日记

  • Post author:
  • Post category:其他


<Codeforces 1004B>

题意:

有n个花盆,放两种花A,B,有m个区间,每个区间的价值是:A花个数 * B花个数。问怎么摆放花让所有区间的价值和最大。

思路:

设每段区间 A 花有 a 个,B 花有 b 个,根据均值不等式,当 a * b 取最大值时,当且仅当 a == b。所以要求每段区间内 a == b即可。所以只需要将A、B交替摆放,就能让每段区间的A花个数等于B花个数。

本人AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxx = 1e3 + 98;
int n, m;
int l, r;

int main() {
	cin >> n >> m;
	for(int i = 1; i <= m; i++) cin >> l >> r;
	for(int i = 1; i <= n; i++) {
		if(i & 1) cout << 1;
		else cout << 0;
	}
	cout << endl;
}

<Codeforces 1003D>

题意:

有 m 个具有某些面值的硬币,有 q 个查询,代表 q 个价格,问恰好组成这 q 个价格所需最少硬币数是多少,没有答案打印-1。

思路:

这题就是个贪心,从大往小贪,开一个map对每个面值都记录一下出现次数,然后

ans的累加有两种方式,比如说碰到面值x,那么要构成我当前的m(价格)值,第一种就是需要(m / x)个硬币,第二种就是需要mp[x]个硬币,所以贪心就,每次都取两者较小的那个即可。核心代码如下:

for(ll i = Inf; i >= 1; i >>= 1) {
			ll tmp = min(mp[i], m / i);
			ans += tmp;
			m -= tmp * i;
		}

为什么每次取两者较小值呢,首先就像我之前说的,肯定面值越大的优先,就是从大往小进行贪心,当我遇到面值x,我最多能提供mp[x]个x,如果说我当前 m / x 比 mp[x] 多,显然是提供 m / x个最好,但是我只能提供 mp[x]个,我也很无奈,所以我只能选mp[x]个;如果说 m / x 比 mp[x]要小,那就意味着,我x本来就最好需要 m / x个,你却有较多的 mp[x]个,那我肯定选最优的m / x个,mp[x]多出的那些没用了,综上取两者较小者。

然后每次让价值m减掉当前硬币面值乘需要个数即可,如果m减不到0,就打印-1,否则打印ans。

本人AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll Inf = 1 << 30;
const int maxx = 2e5 + 7;
map <ll, ll> mp;
ll n, q;
ll a[maxx];
ll m, ans;

int main() {
	cin >> n >> q;
	mp.clear();
	for(ll i = 1; i <= n; i++) {
		cin >> a[i];
		mp[a[i]]++;
	}
	while(q--) {
		cin >> m;
		ans = 0;
		for(ll i = Inf; i >= 1; i >>= 1) {
			ll tmp = min(mp[i], m / i);
			ans += tmp;
			m -= tmp * i;
		}
		if(m) cout << "-1" << endl;
		else cout << ans << endl;
	}
}



版权声明:本文为EricGipsy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。