Educational Codeforces Round 122 (Rated for Div. 2) ABCD

A. Div. 7

给一个数,问最少修改多少位可以让这个数被7整除。

注意到7小于10,因此每10个数必然有一个7,所以最多只需要修改一次个位即可。

#include <iostream>
#include <cmath>
#define ll long long
using namespace std;
int main() {
	int t;
	cin >> t;
	while(t--) {
		int n;
		cin >> n;
		if(n % 7 == 0) cout << n << endl;
		else {
			int a = n / 10 * 10;
			for(int i = 0; i < 9; i++) {
				if((a + i) % 7 == 0) {
					cout << a + i << endl;
					break;
				}
			}
		}
	}
	return 0;
}

B. Minority

给一个01字符串,可以选择一个子串,如果其中0的个数严格大于1的个数则将1删掉,如果1的个数严格大于0的个数则将0删掉,问最多能删掉多少数。

首先如果整个串中0和1个数不一样,那么直接选整个串即可;如果一样的话,则选除这个串第一个字符外剩下所有字符构成的子串,这样显然答案最大。

#include <iostream>
#include <cmath>
#define ll long long
using namespace std;
int main() {
	int t;
	cin >> t;
	while(t--) {
		string s;
		cin >> s;
		int zero = 0, one = 0;
		for(int i = 0; i < s.size(); i++) {
			if(s[i] == '0') zero++;
			else one++;
		}
		if(zero == one) cout << zero - 1 << endl;
		else cout << min(zero, one) << endl;
	}
	return 0;
}

C. Kill the Monster

最关键的是要注意到k的范围总共才2e5,自然想到枚举k然后判断能否击败。几百的条件是character攻击的次数小于等于怪物攻击的次数。

#include <iostream>
#include <cmath>
#define ll long long
using namespace std;
ll hc, dc, hm, dm, k, w, a;
bool check() {
	ll num1 = ceil(1.0 * hm / dc);
	ll num2 = ceil(1.0 * hc / dm);
	return num1 <= num2;
}
int main() {
	int t;
	cin >> t;
	while(t--) {
		cin >> hc >> dc;
		cin >> hm >> dm;
		cin >> k >> w >> a;
		//注意k的和不超过2e5
		bool ok = 0;
		for(ll i = 0; i <= k; i++) {//有i个加hc
			hc += i * a;
			dc += (k - i) * w;
			if(check()) {
				ok = 1;
				break;
			}
			hc -= i * a;
			dc -= (k - i) * w;
		}
		if(ok) puts("YES");
		else puts("NO");
	}
}

D. Make Them Equal

首先注意到,因为每个ai起始都为1,因此ai到达bi的次数是固定的。可以预处理出1到1000范围内从1变换到每个数的次数,然后实际上这个问题就变成了一个最简单的01背包模型。预处理的话我一开始想到的是倍增/枚举因子贪心,然而实际上这样得到的不一定是最优解。一个正确的做法是求一遍最短路,起点为1,a到b路径长度是从a变换到b的次数。还有一点需要注意,输入说明中显示k范围1e6,如果dp数组第二维直接开1e6必然TLE/MLE。而b的范围是1000,按照纯倍增做法,一个数至多变换2log1000次,如果再枚举因子贪心的话变换次数还会降低,实测每个数变换次数上界为13,因此若干k大于n * 13则直接取k = n * 13即可。

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
int n, k, dp[13005], a[1005], b[1005], c[1005], num[1005], f[1005], v[1005];
void dijkstra() {
	memset(v, 0, sizeof(v));
	memset(f, 0x3f, sizeof(f));
	priority_queue<pair<int, int> > q;
	f[1] = 0;
	q.push(make_pair(0, 1));
	while(q.size()) {
		int now = q.top().second;
		q.pop();
		if(v[now]) continue;
		v[now] = 1;
		for(int i = 1; i <= now; i++) {
			int nxt = now + now / i;
			if(nxt <= 1000 && f[nxt] > f[now] + 1) {
				f[nxt] = f[now] + 1;
				q.push(make_pair(-f[nxt], nxt));
			}
		}
	}

}
int main() {
	int t;
	cin >> t;
	
	dijkstra();
	while(t--) {
		cin >> n >> k;
		for(int i = 0; i <= 13000; i++) dp[i] = 0;
		for(int i = 1; i <= n; i++) {
			cin >> b[i];
			a[i] = 1;
			num[i] = 0;
		}
		for(int i = 1; i <= n; i++) {
			cin >> c[i];
		}
		for(int i = 1; i <= n; i++) {
			num[i] = f[b[i]];
		}
		int ans = 0;

		for(int i = 1; i <= n; i++) {
			for(int j = min(k, 13 * n); j - num[i] >= 0; j--) {
				dp[j] = max(dp[j], dp[j - num[i]] + c[i]);
				ans = max(ans, dp[j]);
			}
		}
		cout << ans << endl;
	} 
	return 0;
}
// 7 12
// 11 57 71 26 31 99 58
// 62 66 82 31 94 18 74
上一篇:无法加载类“org.slf4j.impl.StaticLoggerBinder“异常处理


下一篇:CF1631F:Flipping Range(dp)