A - Past ABCs
时间限制:2秒 内存限制:1024MB
分数:100分
问题描述
给定一个长度为 6 的字符串 S。保证 S 的前三个字符是 ABC,而后三个字符是数字。判断 S 是否是在这个竞赛开始之前由 AtCoder 举办并结束的竞赛的缩写。在这里,一个字符串 T 是在这个竞赛开始之前由 AtCoder 举办并结束的竞赛的缩写,当且仅当它等于以下 348 个字符串之一:
ABC001, ABC002, …, ABC314, ABC315, ABC317, ABC318, …, ABC348, ABC349.
注意ABC316不包括在内。
限制
- S是一个长度为 6 的字符串,其中前三个字符是 ABC,而后三个字符是数字。
输入格式
输出格式
如果 S 是在这个竞赛开始之前由 AtCoder 举办并结束的竞赛的缩写,则输出 Yes;否则,输出 No。
输入输出样例
输入样例1
输出样例1
ABC349 是上周在 AtCoder 上举办并结束的比赛的缩写。
输入样例2
输出样例2
ABC350 是这次比赛,尚未结束。
输入样例3
输出样例3
ABC316 并没有在 AtCoder 上举办。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
int d = (s[3] - '0') * 100 + (s[4] - '0') * 10 + s[5] - '0';
if (s[0] == 'A' && s[1] == 'B' && s[2] == 'C') {
if (d >= 1 && d <= 349 && d != 316) { printf("Yes"); return 0; }
}
printf("No");
return 0;
}
B - Dentist Aoki
时间限制:2秒 内存限制:1024MB
分数:200分
问题描述
Takahashi 有 N 颗牙齿,分别在编号为 1,2,…,N 的洞里面。牙医 Aoki 将会对这些牙齿和洞进行Q次治疗。
在第 i 次治疗中,对洞 的处理如下:
- 如果洞 中有一颗牙齿,则将牙齿从洞 中取出。
- 如果洞 中没有牙齿(即洞是空的),则在洞 中种植一颗牙齿。
完成所有治疗后,Takahashi 有多少颗牙齿?
限制
- 所有输入的值都是整数。
输入格式
输出格式
输出一个表示牙齿数量的整数
样例输入输出
输入样例1
输出样例1
开始时,Takahashi 有 30 颗牙齿,Aoki 进行了六次治疗。
- 在第一次治疗中,处理了第 2 号洞。洞中有一颗牙齿,因此将其移除。
- 在第二次治疗中,处理了第 9 号洞。洞中有一颗牙齿,因此将其移除。
- 在第三次治疗中,处理了第 18 号洞。洞中有一颗牙齿,因此将其移除。
- 在第四次治疗中,处理了第 27 号洞。洞中有一颗牙齿,因此将其移除。
- 在第五次治疗中,处理了第 18 号洞。洞中没有牙齿,因此长出一颗新牙。
- 在第六次治疗中,处理了第 9 号洞。洞中没有牙齿,因此长出一颗新牙。
最终的牙齿数为 28 颗。
输入样例2
输出样例2
输入样例3
输出样例3
代码
#include <bits/stdc++.h>
using namespace std;
int n, q, t[1005], vis[1005], cnt = 0;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int main() {
n = read(), q = read();
for (int i = 1; i <= q; i++) {
t[i] = read();
vis[t[i]] ^= 1;
} // 0为有牙, 1为无牙
for (int i = 1; i <= n; i++) if (!vis[i]) cnt++;
cout << cnt;
return 0;
}
C - Sort
时间限制:2秒 内存限制:1024MB
分数:300分
问题描述
给定一个对于 1,2,…, N 的排列 。
通过执行以下操作,将 A 转换为 (1,2,…,N),操作可以执行 0 到 N - 1 次,包括 0 和 N - 1:
操作:选择任意一对整数(i,j),使得1 ≤ i < j ≤ N。交换 A 中第 i 个位置和第 j 个位置的元素。
可以证明,在给定的约束条件下,总是可以将 A 变换为(1,2,…,N)。
限制
- 是 1,2,…, N 的全排列
- 所有输入的值都是整数。
输入格式
输出格式
设 K 为操作的次数。输出 K + 1 行。
第一行输出 K。
第 (l + 1) 行(1 ≤ l ≤ K)应包含选定用于第 l 次操作的整数 i 和 j,用一个空格分隔。
任何满足问题描述中条件的输出都是正确。
输入输出样例
输入样例1
输出样例1
操作会改变序列如下:
- 初始时,A = (3,4,1,2,5)。
- 第一次操作交换第一个和第三个元素,变为 A = (1,4,3,2,5)。
- 第二次操作交换第二个和第四个元素,变为 A = (1,2,3,4,5)。
一下其他类似的输出也是正确的:
输入样例2
输出样例2
输入样例3
输出样例3
思路
由于 所以如果使用冒泡排序的话一定会超时,需要考虑 时间复杂度的算法。我们可以开一个 vis 数组来存 1,2,…,N 中每个元素的位置,当 a[ i ] 不等于 i 的时候再进行交换,同时用一个 vector 储存被选取得整数对 i,j ,最后按照格式输出即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, a[N], vis[N], flag = 0;
vector<pair<int,int>> v;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int main() {
n = read();
for (int i = 1; i <= n; i++) {
a[i] = read();
if (a[i] != i) flag = 1;
vis[a[i]] = i;
}
if (flag) {
for (int i = 1; i <= n; i++) {
if (a[i] != i) {
v.push_back(make_pair(i, vis[i]));
vis[a[i]] = vis[i];
a[vis[i]] = a[i];
vis[i] = i;
}
}
}
printf("%d\n", v.size());
for (auto i : v) printf("%d %d\n", i.first, i.second);
return 0;
}
E - Toward 0
时间限制:2秒 内存限制:1024MB
分数:450分
问题描述
题目给定一个整数 N。你可以进行以下两种操作:
1. 支付 X 日元,将 N 替换为 。
2. 支付 Y 日元,掷一个显示 1 到 6 之间整数的骰子(各数值出现的概率相同)。设掷出的结果为 b,将 N 替换为 。
这里, 表示不大于 s 的最大整数。例如, 和 。
你需要确定在最优选择操作的情况下,使 N 变为 0 之前所支付的最小预期费用。
每次操作中的骰子结果是相互独立的,并且可以在观察到前一次操作结果后再选择操作。
限制
- All input values are integers.
输入格式
输入内容由标准输入提供,格式如下:
输出格式
输出答案。
如果输出的绝对误差或相对误差与正确答案最多为 ,则视为正确。
输入输出样例
输入样例1
输出样例1
可用的操作如下:
- 支付 10 日元,将 N 替换为 。
- 支付 20 日元,掷一个骰子。设结果为 b,将 N 替换为 。
最优策略是执行第一种操作两次。
输入样例2
输出样例2
可用的操作如下:
- 支付 10 日元,将 N 替换为 。
- 支付 20 日元,掷一个骰子。设结果为 b,将 N 替换为 。
最优策略如下:
首先,执行第二种操作来掷骰子。
如果结果是 4 或更大,那么 N 变为0。
如果结果是 2 或 3,那么 N 变为1。此时,执行第一种操作使 N = 0。
如果结果是 1,则重新开始。
输入样例3
输出样例3
思路
分别对于两种操作求期望,利用map来储存期望值
操作1:
操作2:
由于等式两边都有 ,因此可以进行化简(否则在实际操作的时候由于 会一直调用 陷入死循环),化简后结果是
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double //提高精度
int n, a, x, y;
map<int, double> mp;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
double dfs(int tar) {
if (tar == 0) return 0.0;
if (mp[tar]) return mp[tar];
double ans = y;
for (int i = 2; i <= 6; i++) ans += dfs(tar / i) + y;
ans /= 5.0;
mp[tar] = min(ans, dfs(tar / a) + x);
return mp[tar];
} // 记忆化搜索
signed main(){
n = read(), a = read(), x = read(), y = read();
dfs(n);
printf("%.15Lf\n", mp[n]);
return 0;
}