Codeforces Round #544(Div. 3)--B Preparation for International Women's Day(简单思维题)

Preparation for International Women’s Day

time limit per test 2 seconds
memory limit per test 256 megabytes
题目链接https://codeforces.com/contest/1133/problem/B

International Women’s Day is coming soon! Polycarp is preparing for the holiday.

There are nn candy boxes in the shop for sale. The i-th box contains di candies.

Polycarp wants to prepare the maximum number of gifts for kk girls. Each gift will consist of exactly two boxes. The girls should be able to share each gift equally, so the total amount of candies in a gift (in a pair of boxes) should be divisible by kk. In other words, two boxes i and j (i≠j) can be combined as a gift if d i + d j di+dj di+dj is divisible by kk.

How many boxes will Polycarp be able to give? Of course, each box can be a part of no more than one gift. Polycarp cannot use boxes “partially” or redistribute candies between them.

在这里插入图片描述
Examples
input
7 2
1 2 2 3 2 4 10

output
6

input
8 2
1 2 2 3 2 4 6 10

output
8

input
7 3
1 2 2 3 2 4 5

output
4

Note
In the first example Polycarp can give the following pairs of boxes (pairs are presented by indices of corresponding boxes):

(2,3);
(5,6);
(1,4)
So the answer is 66.

In the second example Polycarp can give the following pairs of boxes (pairs are presented by indices of corresponding boxes):

(6,8);
(2,3);
(1,4);
(5,7).
So the answer is 88.

In the third example Polycarp can give the following pairs of boxes (pairs are presented by indices of corresponding boxes):

(1,2);
(6,7).
So the answer is 44.


题目的大意是这样的,给你一个数组代表第i个盒子的糖果,问你可以使用几个盒子,(盒子是成对出现且两个盒子里的糖果数相加必须为k的倍数)。
emmm。。首先想到的是暴力,双层for

for (int i=1; i<=n; i++)
		if (!v[i])
			for (int j=i+1; j<=n; j++) {
				if ((a[i]+a[j])%k==0 && !v[j]) {
					ans+=2;
					v[j]=1;
					break;
				}
			}

虽然有2s的时限,但双层for即使经过了优化也只跑了18组数据(当然没优化的话不到5组)
在这里插入图片描述
但仔细想一想就会明白,假如a为b的倍数,c不是b的倍数,那么a+c绝对不会是b的倍数。所以我们直接在输入的同时判断是否为k的倍数,然后sum++,再判断它的奇偶性。
对于不是k倍数的,我们可以先将它保存下来,然后挨个查找,结果发现,a[i]的数据在1到10亿,无法存储,我们就想到要压缩该数据。
接下来,想想如果(a+b)%k=0的话a%k+b%k也会等于0。又k<100,所以我们需要检索的范围也就缩小到了1到100;然后按照之上的暴力方法暴力一遍也就过了。。。
在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[200050],v[200050];
int main() {
	int n,k,ans=0,num=0;
	scanf ("%d%d",&n,&k);
	for (int i=1; i<=n; i++) {
		scanf ("%d",&a[i]);
		if (a[i]%k==0) num++;    //是否为k的倍数
		else v[a[i]%k]++;        //压缩数据大小
	}
	ans=num/2;
	ans*=2;
	for (int i=1; i<k; i++)
		if (v[i])
			for (int j=i; j<k; j++) {
				if (i==j && (i+j)%k==0) {
					int ss=v[i]/2;
					ans+=ss*2;
					v[i]-=ss*2;
					if (v[i]) continue;
					else break;
				} 
				else if(v[j] && (i+j)%k==0){
					if (v[i]>v[j]) {
						ans+=2*v[j];
						v[i]-=v[j];
						v[j]=0;
						continue;
					} else {
						ans+=2*v[i];
						v[j]-=v[i];
						v[i]=0;
						break;
					}
				}
			}
	printf ("%d\n",ans);
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值