A. Nearest Interesting Number(简单题)
题目链接:codeforces 1183A
题意:
给一个数,输出大于等于这个数并且这个数的每一位的和相加 余 4 == 0
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, m;
cin >> m;
int ans = 0;
for(int i = 0; i <= 100; i++){
n = m + i;
ans = 0;
while(n){
ans = ans + n % 10;
n = n / 10;
}
if(ans % 4 == 0){
cout << m + i << endl;
break;
}
}
return 0;
}
B. Equalize Prices(简单思维)
题目链接:codeforces 1183B
题意:
给n个数,问是否能将这些数改变成同一个数,然后这个数和本身相差 不超过 k,如果能,输出这个数的最大值,否则输出-1
题解:
如果不能,只有一种情况,最大值和最小值的差 大于 k的2倍
如果可以,那么答案就是 最小值加上 k
#include<bits/stdc++.h>
using namespace std;
int main(){
int q;
cin >> q;
while(q--){
int n, k;
cin >> n >> k;
int a, mi = 1e8+1, ma = 0;
for(int i = 1; i <= n; i++){
cin >> a;
mi = min(mi, a);
ma = max(ma, a);
}
if((ma - mi) > k * 2){
cout << -1 << endl;
}
else{
cout << mi + k << endl;
}
}
return 0;
}
C. Computer Game(思维)
题目链接:codeforces 1183C
题意:
电脑初始为 k 格电,有 n 局游戏,每玩第一种游戏消耗 a格电,每玩第二种游戏消耗 b格电,问最多能玩多少次第一种游戏,如果不能玩够 n 局游戏,输出-1(当前电量只有严格大于玩游戏消耗的电量,才能够玩游戏)
题解:
首先判断是否能够玩 n 局游戏,肯定是 k > min(a, b) * n;
如果第一种游戏耗电量 <= 第二种,那么就只玩第一种 ans = min(a, k/a) * n;
如果第一种游戏耗电量 > 第二种, ans = min(n, (k-1-n*b) / (a - b) ) [ 解释 : (k-1-n*b)的意思为 全部玩 b 剩余的电量,(a-b)为 两种游戏的电量差 ]
{ 举例解释 :
15(初始电量) 5(5局游戏) 5(玩第一种每次耗电为5) 1(玩第二种游戏每次耗电为1)
首先肯定可以玩够5局,因为 1 * 5 < 15,其次要尽量多玩第一种游戏,那么(k-1-n*b) 就是玩第二种游戏多出来的电,可以将这些电分给 玩第一种游戏,同时扣掉玩1局第二种游戏
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int q;
cin >> q;
while(q--){
ll k, n, a, b;
cin >> k >> n >> a >> b;
if(k <= min(a, b) * n){
cout << -1 << endl;
}
else{
if(a <= b){
cout << min(k/a, n) << endl;
}
else{
cout << min(n, (k-1-n*b) / (a-b)) << endl;
}
}
}
return 0;
}
D. Candy Box (easy version)(模拟)
题目链接:codeforces 1183D
题意:
一个盒子里有 n 块糖,输入n个数,代表a[i] 代表 a[i] 种类的糖数加一,拿出n块糖作为礼物,要求每种类的糖数要不一样,求最多拿出多少块糖。
举例
16
2 1 3 3 4 3 4 4 1 3 2 2 2 4 1 1
有4种糖,每种糖的数量都是4,所以拿出的糖的个数为 4 + 3 + 2 + 1 = 10
题解:
简单模拟, 坑点,memset(a, 0, sizeof(a)) 的时间复杂度高于 循环
方法一:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+1;
int main(){
int q;
cin >> q;
while(q--){
int n;
cin >> n;
int a[maxn];
// 刚开始memset(a, 0 ,sizeof(a)) 超时
for(int i = 1; i <= n; i++){
a[i] = 0;
}
for(int i = 1; i <= n; i++){
int k;
cin >> k;
a[k]++;
}
sort(a+1, a+1+n);
int ans = a[n], i = 1, k = a[n];
for(int i = n-1; i >= 1; i--){
if(a[i] >= k){
ans += min(k-1, a[i]);
k--;
}
else{
k = a[i];
ans += a[i];
}
if(a[i] == 0 || k <= 1){
break;
}
}
cout << ans << endl;
}
return 0;
}
方法二: 使用map和优先队列
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+100;
struct Node {
int sum;
bool operator < (const Node &x) const {
return this->sum < x.sum;
}
};
int n, t;
map <int, int> mps;
priority_queue <Node> qu;
void init() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
int type;
scanf("%d", &type);
mps[type]++;
}
map <int, int> :: iterator iter;
for(iter = mps.begin(); iter != mps.end(); iter++) {
Node now = {iter->second};
qu.push(now);
}
}
int main() {
scanf("%d", &t);
while(t--) {
init();
int now = qu.top().sum+1;
int ans = 0;
while(!qu.empty()) {
int sum = qu.top().sum;
qu.pop();
if(now == 0 || sum == 0) break;
if(sum < now) {
now = sum;
ans += sum;
}
else{
now--;
ans += now;
}
}
while(!qu.empty()){
qu.pop();
}
mps.clear();
printf("%d\n", ans);
}
return 0;
}
E. Subsequences (easy version)(模拟)
题目链接:codeforces 1183E
题意:
给出一个长度为n的字符串,问是否存在k个不同的子序列,然后求子序列的最小花费(每删除一个字符为一个花费)
题解:
将所有子序列存在set中,判断set的大小是否大于k,先将初始字符串每次从头开始删一个元素,然后存入队列和set中,每次取队列的首元素,重复操作
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+1;
set<string> se;
int main(){
string s;
ll n, k, ans = 0;
cin >> n >> k >> s;
queue<string> q;
q.push(s);
set<string> se;
se.insert(s);
while(!q.empty() && se.size() < k){
string ne = q.front();
q.pop();
for(int i = 0; i < ne.size(); i++){
string v = ne;
v.erase(i, 1);
if(!se.count(v) && se.size() < k) {
q.push(v);
se.insert(v);
ans += n - v.size();
}
}
}
if(se.size() < k){
cout << -1 << endl;
}
else{
cout << ans << endl;
}
return 0;
}
G. Candy Box (hard version) (STL)
题目链接:codeforces 1183G
题意:
一个盒子里有 n 块糖,输入n个数,代表a[i] 代表 a[i] 种类的糖数加一,并且每个糖果有一个你是否喜欢的标记(0喜欢,1不喜欢),拿出n块糖作为礼物,要求每种类的糖数要不一样,,问糖果最多可以选择多少个,在保证糖果最大的情况下,要求标号为1的糖果最多,输出最大的糖果数和标号为1的糖果数。
题解:
先按糖数大小排序,如果相同,然后按1的个数排序,如果糖果数相等,优先选1最多的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node {
int sum, cnt1;
bool operator < (const Node &x) const {
if (this->sum != x.sum)
return this->sum < x.sum;
else
return this->cnt1 < x.cnt1;
}
};
int n, t;
map <int, int> maps, map1;
priority_queue <Node> qu;
void init() {
scanf("%d", &n);
for(int i=1;i<=n;i++) {
int type, f;
scanf("%d%d", &type, &f);
maps[type]++;
map1[type] += f;
}
map <int, int> :: iterator iter;
for(iter = maps.begin(); iter != maps.end(); iter++) {
Node now = {iter->second, map1[iter->first]};
qu.push(now);
}
}
int main() {
scanf("%d", &t);
while(t--){
init();
int now = 0;
int ans = 0, cnt = 0;
while(!qu.empty()) {
int sum = qu.top().sum;
int cnt1 = qu.top().cnt1;
qu.pop();
if(sum == 0) break;
if(sum != now) {
now = sum;
ans += sum;
cnt += cnt1;
}
else{
if(sum == cnt1) {
sum--;
cnt1--;
}
else{
sum--;
}
qu.push({sum, cnt1});
}
}
while(!qu.empty()) qu.pop();
maps.clear();
map1.clear();
printf("%d %d\n", ans, cnt);
}
return 0;
}