1
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
int main()
{
int n, k;
cin >> n;
cin >> k;
vector<int> v(n, 0);
unordered_map<int, int> m;
int maxElement = 0;
for (int i = 0; i < n; ++i)
{
cin >> v[i];
m[v[i]%k]++;
maxElement = max(maxElement, m[v[i]%k]);
}
cout << maxElement;
return 0;
}
2
解题思路:k个1最多组成k-1对相邻1(连续k个1),最少则是k-1-(n-k),t在这个范围之内可以通过把0依次插入连续的1之间来构造得到(每插入一个0减少一个相邻对)
代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, k, t;
cin >> n >> k >> t;
// 相邻 1 max: k-1 min: k-1-(n-k)
if (t <= k-1 && k <= n && k-1- (n-k) <= t){
string s = "";
int p = k - 1 - t; // 插入 10
while(p--){
s += "10";
}
p = k - (k-1-t); // 插入剩下的 1
while(p--){s += "1";}
p = n - k - (k-1-t); // 还有 0 则继续插入
while(p--){s += "0";}
cout << s;
}
else cout << -1;
}
说明:可以通过下面的例子理解
n = 6, k = 4 时
相邻 1 max:k-1 = 3 min: k-1-(n-k)=1
①t = 3 时,插入10: k-1-t=0 个
接着插入剩下的1: k-(k-1-t)=4个
继续插入剩下的0: n-k-(k-1-t)=2个
最终得到:111100
②t = 1 时同理,最终得到:101011
3
解题思路:先确定一个解的范围,然后通过二分+验证来找到解。需要注意的是验证答案的时候把k刚好用完不一定是最优解,应该按照剩下的k>=0算合法解来逼近最优解
代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
ll a[1000];
int n;
ll k, x;
bool check(ll target)
{
ll tmp = k;
for (int i = 0; i < n; ++i)
{
tmp -= max(0LL, ((a[i] - target) + x - 1) / x);
if (tmp < 0)
return false;
}
if (tmp >= 0)
return true;
return false;
}
int main()
{
cin >> n >> k >> x;
ll maxx = 0;
for (int i = 0; i < n; ++i)
{
cin >> a[i];
maxx = max(a[i], maxx);
}
ll l = maxx - k * x, r = maxx;
ll mid;
while (l <= r)
{
mid = (l + r) >> 1;
if (check(mid))
{
r = mid - 1;
}
else
l = mid + 1;
}
cout << l;
}
要点:(a[i] - target) + x - 1) / x 是把所有数字减到小于等于b所需要的最小操作次数
补充一道类似的题:
给定一个数组 a,包含 n 个整数
再给定一个整数 k,可以给数组中任意整数加 1,总共可以加 k 次
加完 k 次后,找到数组中的最大值。最后要求得一个最小的最大值
题解:找出数组中最大的那个数p,求出数组中所有数与p的差值之和m 如果差值之和大于等于k,则最后最大值为p 否则为 ceil((k-m)/n)+p
作者:苏州小朋友 链接:leetcode.cn/circle/disc… 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。