Codeforces Round #653 (Div. 3) D. Zero Remainder Array(思维)(map)

Zero Remainder Array:

题目大意:(文末有原题)

给你n个整数,且x=0,每次要么x++,要么使ai++并且x++,判断最少通过多少次操作后,可以使任意ai % k = 0;

思路:(暴力会TLE)

因为不论哪个操作,x均会自增1,即x的每个值只能使用一次;

所以对于每种余数,x每增加k,只会多一个数能整除k(设有n个ai 对k的余数是k-1,那么x每增加k,这个n变为n-1,具体看例子);

所以我们需判断出,在余数1~k-1中,数量最多的是哪个(假设最多的数量是s,并且这个余数是c),然后使x从0加到 s * k - c + 1,(即 (s - 1) * k + (k - c) + 1)(加1是因为最后一步,需要把 s * k - c 加到ai上),这个数即是答案;

比如数组是1, 1, 1, k是3:

首先2能使一个1变为3(3%3 = 0),之后5会使另一个1变为6(6%3=0),之后8会使最后一个1变为9(9%3=0);

ans = 3 * 3 - 1 + 1 = 9;

 

比如数组是1, 1, 1, 1,2, 2, k是3:

1 + 2 = 3,

2 + 1 = 3, 

4 + 2 = 6;

5 + 1 = 6;

8 + 1 = 9;

11 + 1 = 12;

在这个数组中,s = 4, c = 1, 对于余数个数不足s的,在x从0增加到s * k - c + 1的过程中,会顺带的使其能够整除k;

如果我们有许多种余数的个数均是最多的s,那么我们此时的c应该是余数最小的那个,因为余数最小,所需要加的值最大;(1如果想要整除100,需要加99;而90想要整除100,只需加上10);

)。

代码:

#include <iostream>
#include <map>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f

int main() {
	ll t;
	cin >> t;
	while(t--) {
		ll n, k, max = 0, mini = INF, s = 0, d = 0;
		cin >> n >> k;
		map<ll, ll> a;
		
		for(ll i = 0; i < n; i++){
			ll x;
			cin >> x;
			if(x % k){
				a[x % k]++;
				if(a[x % k] > max){
					d = 1;
					max = a[x % k];
				}
 			}
		}
//注意要使用迭代器,不能直接从i = 1 遍历到 i = k,因为这样会创建许多本来没有的map;
//例如k = 10000,但是有的只有m[1]和m[2],但是在从1~9999的过程中,会创建m[2]、m[3]...,这样就造成了内存的浪费,并且会MLE 
		for(auto it = a.begin(); it != a.end(); it++) {	
			if(it->second == max) {
				if(it->first < mini)
					mini = it->first;
			}
		}
		
		if(d)
			s = a[mini] * k - mini + 1;
		cout << s << endl;
	}
	
	return 0;
}

原题:

题目:

You are given an array a consisting of n positive integers.

Initially, you have an integer x=0 . During one move, you can do one of the following two operations:

  1. Choose exactly one i from 1 to n and increase ai by x (ai:=ai+x ), then increase x by 1 (x:=x+1 ).
  2. Just increase x by 1 (x:=x+1 ).

The first operation can be applied no more than once to each i from 1 to n .

Your task is to find the minimum number of moves required to obtain such an array that each its element is divisible by k (the value k is given).

You have to answer tt independent test cases.

输入:

The first line of the input contains one integer t (1≤t≤2⋅10^4 ) — the number of test cases. Then tt test cases follow.

The first line of the test case contains two integers n and k (1≤n≤2⋅10^5;1≤k≤10^9 ) — the length of a and the required divisior. The second line of the test case contains n integers a1,a2,…,an (1≤ai≤10^9 ), where ai is the i -th element of a .

It is guaranteed that the sum of n does not exceed 2⋅10^5 (∑n≤2⋅10^5 ).

输出:

For each test case, print the answer — the minimum number of moves required to obtain such an array that each its element is divisible by k.

样例:

Input:          Output:

5
4 3
1 2 1 3 ------------------------------------ 6
10 6
8 7 1 8 3 7 5 10 8 9 ------------------- 18
5 10
20 100 50 20 100500 ----------------- 0
10 25
24 24 24 24 24 24 24 24 24 24 ---- 227
8 8
1 2 3 4 5 6 7 8 -------------------------- 8

Note

Consider the first test case of the example:

  1. x=0x=0 , a=[1,2,1,3]. Just increase x ;
  2. x=1x=1 , a=[1,2,1,3]. Add xx to the second element and increase x ;
  3. x=2x=2 , a=[1,3,1,3] . Add xx to the third element and increase x ;
  4. x=3x=3 , a=[1,3,3,3] . Add xx to the fourth element and increase x ;
  5. x=4x=4 , a=[1,3,3,6] . Just increase x ;
  6. x=5x=5 , a=[1,3,3,6] . Add xx to the first element and increase x;
  7. x=6x=6 , a=[6,3,3,6] . We obtained the required array.

Note that you can't add x to the same element more than once.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值