@Dmaxiya
2018-08-17T10:23:55.000000Z
字数 5286
阅读 1094
Codeforces
Contests 链接:Codeforces Round #441 (Div. 2)
过题数:4
排名:840/9270
小熊维尼一天要吃 次蜂蜜,而兔子、猫头鹰和屹耳的家里都有蜂蜜,最初他在兔子的家里,先吃一次蜂蜜,接着去另一个朋友的家里吃蜂蜜,假设当他离开某个朋友的家之后,这个朋友家里的蜂蜜就会恢复,给定三个朋友的家之间的距离,问小熊维尼想要吃 次蜂蜜,最少要走多少米。
输入包括四行整数,分别为 ,表示小熊要吃蜂蜜的次数、兔子和猫头鹰家之间的距离、兔子和屹耳家之间的距离以及猫头鹰和屹耳家之间的距离。
输出要吃 次蜂蜜,维尼至少要走的距离。
输入 | 输出 | 提示 |
---|---|---|
3 2 3 1 |
3 | 对于维尼来说最优的策略是:兔子猫头鹰屹耳。 |
1 2 3 5 |
0 | 维尼只要在兔子家吃一次蜂蜜,之后不需要移动任何距离。 |
分别对 和 分情况按贪心策略讨论即可。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <ctime>
#include <functional>
#include <iomanip>
using namespace std;
#define LL long long
int n, a, b, c;
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
while(scanf("%d%d%d%d", &n, &a, &b, &c) != EOF) {
if(n == 1) {
printf("0\n");
} else {
printf("%d\n", min(a, b) + (n - 2) * min(min(a, b), c));
}
}
return 0;
}
给出 个整数的序列 ,从中找出 个数字,使这 个数字两两之间的差能整除 。
第一行包含三个整数 和 ,第二行包含 个整数 。
如果无法找出 个满足要求的数字,就输出 ,否则在第一行输出 ,第二行输出 个满足条件的整数,如果有多解,则输出任意一组。
输入 | 输出 |
---|---|
3 2 3 1 8 4 |
Yes 1 4 |
3 3 3 1 8 4 |
No |
4 3 5 2 7 7 7 |
Yes 2 7 7 |
如果每个数字对 的模数相等,那么这几个数字任意两个数字之间的差一定是 的倍数。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <ctime>
#include <functional>
#include <iomanip>
using namespace std;
#define LL long long
const int maxn = 100000 + 100;
int n, k, m, num, Index;
vector<int> ans[maxn];
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
while(scanf("%d%d%d", &n, &k, &m) != EOF) {
Index = -1;
for(int i = 0; i < n; ++i) {
ans[i].clear();
}
for(int i = 0; i < n; ++i) {
scanf("%d", &num);
ans[num % m].push_back(num);
if((int)ans[num % m].size() >= k) {
Index = num % m;
}
}
if(Index == -1) {
printf("No\n");
continue;
}
printf("Yes\n");
for(int i = 0; i < k; ++i) {
if(i != 0) {
printf(" ");
}
printf("%d", ans[Index][i]);
}
printf("\n");
}
return 0;
}
给定一个数字 ,求有多少个数字 ,满足 ,其中 表示数字 的位数。
输入只有一个整数 。
第一行输出一个整数 ,表示有 个满足条件的数字,接下去 行每行一个整数,表示每个满足条件的整数,按照从小到大的顺序输出。
输入 | 输出 | 提示 |
---|---|---|
21 | 1 15 |
是唯一一个满足条件的数字:. |
20 | 0 | 没有任何数字满足条件 |
从数据范围可以知道,满足条件的数字一定在范围 内,因为 内的数字所有数位的和最大为 ,所以暴力枚举 个数字就能找到所有满足条件的答案。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <ctime>
#include <functional>
#include <iomanip>
using namespace std;
#define LL long long
const int maxn = 300;
int n, cnt;
int ans[maxn];
int get_sum(int num) {
int ret = num;
while(num != 0) {
ret += num % 10;
num /= 10;
}
return ret;
}
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
while(scanf("%d", &n) != EOF) {
cnt = 0;
for(int i = 0; i <= 90; ++i) {
if(n - i >= 0) {
if(get_sum(n - i) == n) {
ans[cnt++] = n - i;
}
}
}
printf("%d\n", cnt);
for(int i = cnt - 1; i >= 0; --i) {
if(i != cnt - 1) {
printf(" ");
}
printf("%d", ans[i]);
}
printf("\n");
}
return 0;
}
对一个长度为 的序列,进行下面的操作:
- 从左到右扫一遍整个序列;
- 如果第 个数字是被标记的,而第 个数字是没有被标记的,就将第 个数字和第 个数字交换。
重复以上步骤,直到无法再对这个序列的任意两个数字进行交换。
定义一个序列的“难度”,为一个序列能进行以上操作的次数,如果这个序列已经不能再交换数字,它的“难度”为 。
最初这个序列没有数字是被标记的,它的“难度”为 ,接着将这个序列每一位上的数字逐一标记,总共标记 次,对这个序列的每次标记,输出这个序列的“难度”。
第一行为一个整数 ,第二行为 的排列 ,表示每次标记的数字为序列的第 项。
输出 个数字 , 表示初始序列的“难度”, 表示第 个数字被标记后序列的难度。
输入 | 输出 | 提示 |
---|---|---|
4 1 3 4 2 |
1 2 3 2 1 | 设 表示没有被标记的数字, 表示被标记的数字,最初没有任何数字可以 被交换,序列的“难度”为 ,第 个数字被标记后,对序列的 操作为: 序列的“难度”为 ,第 个数字被标记后,对序列的操作为: 序列的“难度”为 ,第 个数字被标记后,序列的操作为: 序列的“难度”为 ,第 个数字被标记后,序列的操作为: 序列的“难度”为 。 |
8 6 8 3 4 7 2 1 5 |
1 2 2 3 4 3 4 5 1 |
每次操作的时候,最右边的所有被标记的数字都无法移动,且不在最右边的所有数字中,只能移动一个最右边的数字到最右边,如:
一次操作之后变为
最右边的 个数字都无法移动,而前面的数字里,只有倒数第 个数字能够移动到最右边,所以每次操作只能移动一个数字到最右边,因此总的操作次数就是已经被标记的数字个数 最右边的数字个数,可以用并查集维护。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <ctime>
#include <functional>
#include <iomanip>
using namespace std;
#define LL long long
const int maxn = 300000 + 100;
int n, x;
int fa[maxn], num[maxn];
bool vis[maxn];
void Init() {
for(int i = 1; i <= n; ++i) {
fa[i] = i;
vis[i] = false;
num[i] = 1;
}
}
int Find(int x) {
return (fa[x] == x? x: fa[x] = Find(fa[x]));
}
void unit(int x, int y) {
int xx = Find(x);
int yy = Find(y);
if(xx != yy) {
fa[xx] = yy;
num[yy] += num[xx];
}
}
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
while(scanf("%d", &n) != EOF) {
Init();
printf("1");
for(int i = 1; i <= n; ++i) {
scanf("%d", &x);
vis[x] = true;
if(vis[x - 1]) {
unit(x - 1, x);
}
if(vis[x + 1]) {
unit(x, x + 1);
}
int ans;
if(vis[n]) {
int f = Find(n);
ans = i - num[f] + 1;
} else {
ans = i + 1;
}
printf(" %d", ans);
}
printf("\n");
}
return 0;
}