Codeforces 1133B

本文解析了CodeForces竞赛中一道关于盒子里糖果数量的题目,通过优化算法,使用模运算和计数技巧,避免了O(n^2)的时间复杂度,实现了高效的解答。
题目链接

http://codeforces.com/contest/1133/problem/B

题意

n n n个盒子,第 i i i个盒子里有 d i di di个糖果,给每个人两个盒子,要求 d i + d j di+dj di+dj能被 k k k整除。

问最多能给多少个盒子。

思路

很容易想到的思路是排序之后枚举,看两个数加起来能否被 k k k整除。但是 n n n范围是 1 0 5 10^5 105,这种 O ( n 2 ) O(n^2) O(n2)的做法显然会超时。

我的做法是,对于每个盒子,求出 d i di di % k k k ,记录在数组 c [ i ] c[i] c[i]中,答案就由两部分组成:

  1. 对于 k k k的倍数: c [ 0 ] / 2 c[0] / 2 c[0]/2
  2. 对于不是 k k k的倍数: m i n ( c [ i ] , c [ k − i ] ) min(c[i], c[k - i]) min(c[i],c[ki])

这里k是奇数和偶数的时候有点不一样,需要注意一下。

AC代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<sstream>
#include<cctype>
#include<map>
#include<stack>
#include<queue>
#include<list>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long ll;
const double PI = atan(1.0)*4;
const int INF = 0x7ffffff;
const ll MOD = 1000000007;
const int maxn = 200010;

int a[maxn];
int c[110];

int main()
{
//	freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);
	int n, k, ans = 0;
	scanf("%d%d", &n, &k);
	for(int i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
		a[i] = a[i] % k;
		c[a[i]]++;
	}
	ans += c[0] / 2;
	for(int i = 1; i < k / 2; i++)
		ans = ans + min(c[i], c[k - i]);
	if(k % 2 == 0)
		ans = ans + c[k / 2] / 2;
	else
		ans = ans + min(c[k / 2], c[k - k / 2]);
	printf("%d\n", ans * 2);
	return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值