Codeforces #690(div 3) 部分题解

11 篇文章 0 订阅
8 篇文章 0 订阅

Codeforces #690(div 3) 部分题解

D. Add to Neighbour and Remove

题目链接

大致题意:
给你长度为n的数组a,你能进行的操作就是将任意一个元素a[k],使其任意一个相邻元素 a [ k − 1 ] a[k - 1] a[k1] a [ k + 1 ] a[k + 1] a[k+1]加上 a [ k ] a[k] a[k],并在此操作之后删除元素 a [ k ] a[k] a[k],问你最少进行几次操作能够使得数组中所有元素相等。

题解:
数组总共有n个元素,那么最后剩余的数组个数可能有1个、2个……n个,因此,我们可以枚举最后剩余的数组元素个数。假设剩余k个,那么每个元素的值now应该就是:原来数组元素的总和 / k。
我们从第一个元素开始遍历,依次累加起来,如果当前累加的和等于now,那么now = 0,并接着往后进行累加。如果当前的和大于now,说明这种分组情况不合法,break之后接着枚举下一种剩余个数。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int a[3010];
int main() 
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        ll sum = 0;
        for (int i = 0; i < n; i++) {
        	cin >> a[i];
        	sum += a[i];
        }
        for (int i = n; i >= 1; i--) {
        	if (sum % i) continue;
        	ll now = sum / i;
        	ll cur = 0;
        	bool flag = true;
        	for (int j = 0; j < n; j++) {
        		cur += a[j];
        		if (cur == now) {
        			cur = 0;
        		}
        		if (cur > now) {
        			flag = false;
        			break;
        		}
        	}
        	if (flag) {
        		cout << n - i << endl;
        		break;
        	}
        }
    }
    return 0;
}

E1. Close Tuples (easy version)

题目链接

大致题意:
给你一个长度为n的数组a,让你找到3个元素组合在一起,使其 最大值 - 最小值 不大于2。问总共有几种组合方式。

题解:
在输入元素的过程中,记录当前每个元素已经出现的次数,由于简单版本当中,差值不大于2,因此,我们能够枚举所有可以组合的元素的值,并使用组合数知识计算出目前能够组合的个数,并将此个数加到答案ans里。
比如,当前的元素值是 a [ k ] a[k] a[k],那么,能够与其组合的数有 a [ k − 2 ] , a [ k − 1 ] , a [ k ] , a [ k + 1 ] , a [ k + 2 ] a[k - 2], a[k - 1], a[k], a[k + 1],a[k + 2] a[k2],a[k1],a[k],a[k+1],a[k+2],在这些数当中选取两两差值不超过2的数进行组合即可。具体细节见代码。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 10;
map<int, ll> num;
int a[MAXN];
int main() 
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        ll ans = 0;
        num.clear();
        for (int i = 0; i < n; i++) {
        	cin >> a[i];
            num[a[i]]++;
            if (i >= 2) {
                ll sum = num[a[i] - 2] + num[a[i] - 1];
                if (sum >= 2) {
                    ans += ((sum - 1) * sum / 2); // 选取当前a[i],在a[i] - 1和a[i] - 2中再选2个
                }
                if (num[a[i]] > 1 && sum >= 1) {
                    ans += (num[a[i]] - 1) * sum; // 选取2个a[i],在a[i] - 1和a[i] - 2中再选1个
                }
                if (num[a[i]] >= 2) {
                    ans += (num[a[i]] - 1) * (num[a[i]] - 2) / 2; // 3个数都选a[i]
                }
                ans += num[a[i] - 1] * num[a[i] + 1]; // 选一个a[i] - 1,一个a[i] + 1和当前数
                sum = num[a[i] + 1] + num[a[i] + 2];
                if (sum >= 2) {
                    ans += (sum - 1) * sum / 2; // 选取当前a[i],在a[i] + 1和a[i] + 2中再选2个
                }
                if (num[a[i]] > 1 && sum >= 1) {
                    ans += (num[a[i]] - 1) * sum; // 选取2个a[i],在a[i] + 1和a[i] + 2中再选1个
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值