AtCoder Regular Contest 139 赛时记录

小掉了 8 分

退役前最后一场 AT 了/ll,好可惜没能上分

A - Trailing Zeros

直接从前向后模拟计算即可。

设计算到了第 \(i\) 个,上一个是 \(a_{i-1}\),那就是求一个满足 \(2^{t_i} + k 2^{t_i+1} > a_{i-1}\) 的最小的 \(k\)

随便计算一下就行。

signed main() {
	n = read();
	for(int i = 1; i <= n; ++i) b[i] = read();
	for(int i = 1; i <= n; ++i) {
		int fir = 1ll << b[i];
		int add = 1ll << (b[i] + 1);
		int lst = a[i - 1];
		int cnt = (lst - fir - 1) / add + 1;
		if(fir > lst) cnt = 0;
		a[i] = fir + add * cnt;
		if(a[i] == a[i - 1]) a[i] += add;
	}
	cout << a[n] << "\n";
	return 0;
}

B - Make N

发现三个操作不好做,如果让它变成两个操作就好做了。

我们讲三个操作分别叫做一操作,二操作,三操作

首先特判出一操作比二操作或者三操作优或者都优的情况。

然后,考虑按照 \(A,B\)\(\sqrt {n}\) 的大小关心进行分讨。

\(A > B\),如果 \(A > \sqrt n\),我们可以暴力枚举用几次 \(A\),然后直接算剩下的贡献,对所有值取个 \(\min\)

否则,我们考虑枚举有几次 \(1\) 操作,显然这个只需要枚举到 \(\max \{A,B\}\) 就好。也是 \(\sqrt n\) 级别。

然后我们确定了 \(A,B\) 要组成一个什么数,这个东西我们可以用 \(\text{exgcd}\) 算一下合法解,因为随着其中一个解的增大,花费的变化是单调的,所以我们取一下两个极端的贡献就好。这个东西是洛谷上的模板题。

然后就做完了,剩下的应该是亿些细节问题。

#include<bits/stdc++.h>
#define LL long long
#define int long long
#define orz cout << "tyy YYDS!!!\n"
using namespace std;
const int MAXN = 2e5 + 10;
const int INF = 1e9 + 7;
const int mod = 998244353;

int T, n, A, B, X, Y, Z;
int ans;

int read() {
	int s = 0, f = 0; char ch = getchar();
	while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
	while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

int x, y;
int Exgcd(int a, int b, int &x, int &y) {
	if(!b) { x = 1, y = 0; return a; }
	int d = Exgcd(b, a % b, x, y);
	int t = x;
	x = y, y = t - a / b * y;
	return d;
}

int Solve(int m) {
	if(!m) return 0;
	x = 0, y = 0;
	int a = A, b = B, c = m;
	int ans = m * X;
	if(m % A == 0) ans = min(ans, m / A * Y);
	if(m % B == 0) ans = min(ans, m / B * Z);
	int d = Exgcd(a, b, x, y);
	if(c % d) return ans;
	else {
		int p = b / d, q = a / d, k;
		x *= c / d, y *= c / d;
		if(x < 0) k = ((-x) / p) + 1, x += p * k, y -= q * k;
		if(x >= 0) k = (x - 1) / p, x -= p * k, y += q * k;
		if(y > 0) {
			int tmp = x, del = c / d;
			ans = min(ans, (tmp * Y + (c - tmp * A) / B * Z));
			tmp = ((y - 1) % q + 1);
			ans = min(ans, (tmp * Z + (c - tmp * B) / A * Y));
			
//			tmp = (x + (y - 1) / q * p);
//			ans = min(ans, del * (tmp * Y + (d - tmp * A) / B * Z));
//			tmp = y;
//			ans = min(ans, del * (tmp * Z + (d - tmp * B) / A * Y));
		} else {
			return ans;
		}
	}
	return ans;
}

void Main() {
	n = read(), A = read(), B = read(), X = read(), Y = read(), Z = read();
	if(Y - A * X >= 0 && Z - B * X >= 0) {
		printf("%lld\n", n * X);
	} else if(Y - A * X >= 0) {
		printf("%lld\n", n / B * Z + n % B * X);
	} else if(Z - B * X >= 0) {
		printf("%lld\n", n / A * Y + n % A * X);
	} else {
		if(A < B) swap(A, B), swap(Y, Z);
		int lim = 100000;
		if(A > lim) {
			ans = n * X;
			for(int i = 0; i * A <= n; ++i) {
				int lst = n - i * A;
				ans = min(ans, i * Y + lst / B * Z + lst % B * X);
			}
			printf("%lld\n", ans);
		} else {
//			assert(0);
			ans = n * X;
			for(int i = 0, M = min(n, max(A, B)); i <= M; ++i) {
				ans = min(ans, i * X + Solve(n - i));
			}
			printf("%lld\n", ans);
		}
	}
}

signed main() {
	T = read();
	while(T--) Main();
	return 0;
}
posted @ 2022-04-24 22:35  Suzt_ilymtics  阅读(164)  评论(1编辑  收藏  举报