VP Educational Codeforces Round 26


A. Text Volume

题意:统计每个单词大写字母个数的最大值。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::string s;
    getchar();
    std::getline(std::cin, s);
    s += " ";
    int ans = 0;
    for (int i = 0, sum = 0; i <= n; ++ i) {
    	if (s[i] == ' ') {
    		ans = std::max(ans, sum);
    		sum = 0;
    	} else {
    		sum += s[i] >= 'A' && s[i] <= 'Z';
    	}
    }

    std::cout << ans << "\n";
}

B. Flag of Berland

题意:有三种颜色,判断是不是每种颜色各占一个三分之一大小的矩阵。

模拟题。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<std::string> s(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> s[i];
    }

    auto check = [&](int x1, int y1, int x2, int y2, char c) -> bool {
    	for (int i = x1; i < x2; ++ i) {
    		for (int j = y1; j < y2; ++ j) {
    			if (s[i][j] != c) {
    				return false;
    			}
    		}
    	}

    	return true;
    };

    if (n % 3 == 0) {
    	std::string p = "RGB";
    	std::vector<int> id{0, 1, 2};
    	do {
    		if (check(0, 0, n / 3, m, p[id[0]]) && 
    			check(n / 3, 0, n / 3 * 2, m, p[id[1]]) && 
    			check(n / 3 * 2, 0, n, m, p[id[2]])) {
    			std::cout << "YES\n";
    			return;
    		}
    	} while (std::next_permutation(id.begin(), id.end()));
    }

    if (m % 3 == 0) {
    	std::string p = "RGB";
    	std::vector<int> id{0, 1, 2};
    	do {
    		if (check(0, 0, n, m / 3, p[id[0]]) && 
    			check(0, m / 3, n, m / 3 * 2, p[id[1]]) && 
    			check(0, m / 3 * 2, n, m, p[id[2]])) {
    			std::cout << "YES\n";
    			return;
    		}
    	} while (std::next_permutation(id.begin(), id.end()));
    } 

	std::cout << "NO\n";
}

C. Two Seals

题意:一个a×b的矩阵,有nxi×yi的印章,放两个进去不重叠能占多少面积。每个小矩阵可以旋转90度。

也是模拟,我们先把一个和左上角贴齐,然后判断是不是另一个能不能放下就行。枚举两个印章各自旋不旋转,各自放一遍。

点击查看代码
void solve() {
    int n, a, b;
    std::cin >> n >> a >> b;
    std::vector<std::pair<int, int>> c(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> c[i].first >> c[i].second;
    }

    auto check = [&](int h1, int w1, int h2, int w2) -> int {
    	if (a < h1 || a < h2 || b < w1 || b < w2) {
    		return 0;
    	}

    	if (a - h1 >= h2 || b - w1 >= w2) {
    		return h1 * w1 + h2 * w2;
    	}

    	return 0;
    };

    int ans = 0;
    for (int i = 0; i < n; ++ i) {
    	auto & [h1, w1] = c[i];
    	for (int j = i + 1; j < n; ++ j) {
    		auto & [h2, w2] = c[j];
    		ans = std::max(ans, check(h1, w1, h2, w2));
    		ans = std::max(ans, check(w1, h1, h2, w2));
    		ans = std::max(ans, check(w1, h1, w2, h2));
    		ans = std::max(ans, check(h1, w1, w2, h2));
    	}
    }

    std::cout << ans << "\n";
}

D. Round Subset

题意:n个数选k个数,使得某尾连续的零最多。

只有质因子25才能贡献末尾零,那么可以记f[i][j][x][y]表示前i个选了j个有x2y5的值。但这样空间和时间都无法接受,发现其值其实就是min(x,y),所以我们可以记f[i][j][x]表示有x5的情况有多少个2。然后滚动数组优化即可。

点击查看代码
void solve() {
    int n, k;
    std::cin >> n >> k;
    std::vector<i64> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    auto get = [&](i64 x) -> std::pair<int, int> {
    	int cnt2 = 0, cnt5 = 0;
    	while (x % 2 == 0) {
    		++ cnt2;
    		x /= 2;
    	}

    	while (x % 5 == 0) {
    		++ cnt5;
    		x /= 5;
    	}

    	return {cnt2, cnt5};
    };

    const int N = n * 26, inf = 1e9;
    std::vector f(k + 1, std::vector<int>(N, -inf));
    f[0][0] = 0;
    int sum5 = 0;
    for (int i = 0; i < n; ++ i) {
    	auto g = f;
    	auto [cnt2, cnt5] = get(a[i]);
    	for (int j = 0; j < k; ++ j) {
    		for (int x = 0; x <= sum5; ++ x) {
    			g[j + 1][x + cnt5] = std::max(g[j + 1][x + cnt5], f[j][x] + cnt2);
    		}
    	}

    	sum5 += cnt5;

    	f = g;
    }

    int ans = 0;
    for (int i = 0; i <= sum5; ++ i) {
    	ans = std::max(ans, std::min(i, f[k][i]));
    }

    std::cout << ans << "\n";
}

E. Vasya's Function

题意:记f(a,0)=0,f(a,b)=1+f(a,bgcd(a,b))。求f(a,b)

这里a一直不变,导致暴力计算不能接受,模拟发现,bagcd在不断增大,于是我们也许可以找下一次gcd变大需要多少次操作。这里要发现f(a,b)=f(agcd(a,b),bgcd(a,b)),因为每次gcd增大后,我们可以让a,b都除以gcd(a,b),那么gcd(a,b)就变成了1。相当于整体缩小了。
那么我们每次找b最少减多少能使得gcd(a,b)1,枚举a的因子即可,但发现因子也是a的质因子的倍数,所以可以枚举a的质因子。判断b到哪个质因子的倍数操作数最小。

点击查看代码
void solve() {
    i64 n, m;
    std::cin >> n >> m;
    std::vector<i64> a;
    i64 ans = 0;
    while (m > 1) {
    	i64 min = m;
    	i64 t = n;
    	for (i64 i = 2; i * i <= n; ++ i) {
    		while (t % i == 0) {
    			min = std::min(min, m % i);
    			t /= i;
    		}
    	}

    	if (t > 1) {
    		min = std::min(min, m % t);
    	}

    	ans += min;
    	m -= min;
    	i64 d = std::gcd(n, m);
    	n /= d, m /= d;
    }

    ans += m;

    std::cout << ans << "\n";
}
posted @   maburb  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示