<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;
}
}