Educational Codeforces Round 164 (Rated for Div. 2)

A. Painting the Ribbon
题意:n个物体,m个颜色,alice要给每个物体任意涂一个颜色。bob可以给k个物体涂色 ,问alice能否阻止bob让所有的物体颜色都相同。

思路:思维题。如果m=1,那么无解。如果m > 1,那么bob如果想要染成同一个颜色,alice可以让bob需要染色的数量最多。如果染色的数量最多,那么m个颜色都要用上,其中颜色最多的part一定是(n - m + 1) / m,这个颜色也就是bob的目标色。 那么bob要染色的数量就是n - (n - m + 1) / m,如果k >= 这个数,那么alice就失败,否则成功。

总结:太久没写cf的题了,想了好久。cf果然是锻炼思维的绝境之地。

void solve(){
	int n, m, k;
	cin >> n >> m >> k;

	if (k >= n - (n + m - 1) / m){
		cout << "NO\n";
	}
	else{
		cout << "YES\n";
	}
}

B. Make It Ugly

题意:一个数组是beautiful的,如果他能够通过这个操作将数组所有的数字变成相同的。 if (a[i - 1] == a[i + 1]) a[i] = a[i - 1];
问:最少删除多少个数字,可以让这个数组不是beautiful的。

思路:依然是思维题,很容易想到如果首末不相等或者所有元素都相等,那么不需要操作。而且需要操作的元素一定跟首元素不相等,我们的目的是让需要操作的元素作为最后一个元素出现,或者让两个需要操作的元素相邻起来(统计两个需要操作元素的中间有多少个元素)。

总结:思维被拷打,最后还没写出来,难题啊,这个代码的思路真的厉害,不仅处理了多个需要修改数值的情况,也考虑删除第一个前面所有字符,删除最后一个后面所有字符,以及全部字符都相等的情况。

void solve(){
    int n;
    cin >> n;

    vector<int> a(n);
    for (auto& x : a){
        cin >> x;
    }

    int ans = n;
    int last = -1;
    for (int i = 0; i <= n; ++i){
        if (i == n || a[i] != a[0]){
            ans = min(ans, i - last - 1);
            last = i;
        }
    }

    if (ans == n){
        ans = -1;
    }
    cout << ans << '\n';
}

C. Long Multiplication

题意:给定2个长度相等的字符串,可以交换字符串中相同位置的字符,求两个字符串相乘值最小时分别是多少。

思路:看输入输出,发现第一个不相等的字符后面,小的都往第一个字符大的串里放,其他的往第一个字符小的串里放。

总结:套路题,研究原理的话要研究一阵子呢,找规律就行。

void solve(){
	string s, t;
	cin >> s >> t;

	int n = int(s.size());

	bool firstTime = true;
	for (int i = 0; i < n; ++i){
		if (s[i] != t[i]){
			if (firstTime){
				if (s[i] < t[i]){
					swap(s[i], t[i]);
				}
				firstTime = false;
			}
			else{
				if (s[i] > t[i]){
					swap(s[i], t[i]);
				}
			}
		}
	}

	cout << s << "\n" << t << '\n';
}

D. Colored Balls

题意:n个颜色的球,每个颜色球的数量给出。定义value为当前若干个颜色球中最小的group数,group最多包含两个球,并且两个球颜色不能相同。
问2 ^ n种球的组合中,value一共是多少。

思路:首先,对于一个单独的组合,如果该组合中的最大值<=其他值的和,那么value就是该组合的(sum + 1) / 2,否则,value就是最大值。也就是说,对于每个组合,value的最小值是(sum + 1) / 2。基于这个思想,先用背包求出所有组合的sum的方案数,可以求出一个ans值。然后,要把剩下的一部分加进去,剩下的这部分怎么求呢?对于每个颜色,如果有某种组合的存在,那么这个组合的sum一定小于该颜色的物品数量a[i],而且之前已经添加过了(a[i] + sum + 1) / 2,只要再添加上a[i] - (a[i] + sum + 1) / 2,就是a[i]剩下的这部分单独一个颜色作为一个group的数量。

总结:只能想到对单个组合进行暴力破解,用dp的话,没想到如何转移这种状态。这个思路真的是太爆炸了,被震撼到了。

void solve() {
	int n;
	cin >> n;
	const int mod = 998244353;
	vector<int> a(n + 1);
	for (int i = 1; i <= n; ++i){
		cin >> a[i];
	}

	int s = std::accumulate(a.begin() + 1, a.end(), 0);
	vector<long long> dp(s + 1);
	dp[0] = 1;
	for (int i = 1; i <= n; ++i){
		for (int j = s; j >= a[i]; --j){
			dp[j] += dp[j - a[i]];
			dp[j] %= mod;
		}
	}

	long long ans = 0;

	for (int i = 1; i <= s; ++i){
		ans += (1ll * i + 1) / 2 * dp[i];
		ans %= mod;
	}

	for (int i = 1; i <= n; ++i){
		for (int j = 0; j < a[i]; ++j){
			ans += (a[i] - (a[i] + j + 1) / 2) * dp[j];
			ans %= mod;
		}
	}
	cout << ans << '\n';
}
posted @   _Yxc  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示