A题 CCPC
中国大学生程序设计竞赛(China Collegiate Programming Contest, CCPC)是由教育部高等学校计算机类专业教学指导委员会主办的面向全国高校大学生的年度学科竞赛,旨在激发学生学习计算机领域专业知识与技能的兴趣,鼓励学生主动灵活地运用计算机知识和技能解决实际问题,有效提升算法设计、逻辑推理、数学建模、编程实现和计算机系统能力,培养团队合作意识、挑战精神和创新能力。
2022年10月23日,CCPC高职专场顺利举行。
你作为第一届CCPC高职专场的参赛者,将顺利地获得你的"AC"。
中国大学生程序设计竞赛的简称为"CCPC",你的任务是对一个"CCPC+年份"的表述检查"CCPC"是否拼写正确。
例如:“CCPC2020"是一个正确的表述,而"CCCC2021"和"ccpc2022"都是不正确的表述(字符区分大小写),注意在这个任务中你并不需要检查年份的合法性。
输入格式:
输入一个长度为8的字符串,输入保证前四个字符为大小写字母,后四个字符为一个合法的年份。
输出格式:
若表述正确,则输出"Hello CCPC!”(不需要输出引号),否则输出"This is not my CCPC"(不需要输出引号)。
输入样例1:
CCPC2022
输出样例1:
Hello CCPC!
输入样例2:
CCPc2019
输出样例2:
This is not my CCPC
#include <bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define PII pair<int, int>
using namespace std;
void solve() {
string s;
cin >> s;
if (s[0] == 'C' && s[1] == 'C' && s[2] == 'P' && s[3] == 'C') {
cout << "Hello CCPC!" << endl;
} else {
cout << "This is not my CCPC" << endl;
}
}
signed main() {
int t = 1;
// cin >> t;
while (t--) {
solve();
}
return 0;
}
B题 道路
D国有n个城市,由于城市之间并没有公路,交通十分不方便。
D国国王希望修建n−1条公路,使得对于任意两个城市,都可以通过公路互相到达。
建造公路的任务由各个城市负责,具体来说,每个城市都会给出建造公路的费用,第i个城市修建公路的费用为di。而对于一条连接x,y两座城市的公路,它的建造任务会由x,y两座城市中修建费用较小的城市来负责修建。整个建造方案的费用为每条公路的建造费用之和。
工程师给出了一个建造方案,但国王认为方案成本略高,他希望工程师修改方案。但出于某种原因,工程师只能在方案中更改不超过k条公路,并且要保证更改后任意两座城市仍然可以通过公路相互到达。你能帮助他算一算在更改方案后最小的建造费用吗?
输入格式:
第一行输入两个正整数n,k(1≤n≤10 ^5 ,0≤k<n)。接下来一行输入n个正整数di(1≤di≤n)表示第i个城市建造公路的费用。
接下来n−1输入初始的建造方案,每个行包含两个正整数x,y(1≤x,y≤n),代表初始建造方案。保证输入是一个合法的方案。
输出格式:
输出一行一个正整数表示最小的成本。
输入样例:
5 1
5 4 3 2 1
1 2
2 4
3 5
1 5
输出样例:
5
将第一条公路修改为连接城市2和城市5的公路是一个最优的更改方案。
#include <bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define PII pair<int, int>
using namespace std;
void solve() {
int n, k, num[100010], a[100010];
cin >> n >> k;
fill(num, num + 100010, 0);
fill(a, a + 100010, 0);
for (int i = 1; i <= n; ++i) cin >> num[i];
for (int i = 1; i <= n - 1; ++i) {
int b, c;
cin >> b >> c;
a[i] = min(num[b], num[c]);
}
sort(a + 1, a + n);
for (int i = n - 1; i > n - 1 - k; --i) {
a[i] = a[1];
}
ll ans = 0;
for (int i = 1; i <= n - 1; ++i) {
ans += a[i];
}
cout << ans << endl;
}
signed main() {
int t = 1;
// cin >> t;
while (t--) {
solve();
}
return 0;
}
D题 函数
这是一个关于函数的问题。
给定一个二次函数y=Ax^2 +Bx+C
求满足x是[L,R]范围内的整数时y的最小值和最大值。
输入格式:
第一行一个正整数T(T≤10^5)代表询问组数。
接下来每行5个整数A,B,C,L,R(−10^6≤A,B,C,L,R≤10 ^6,L≤R)代表询问。
输出格式:
输出T行,每行两个数代表最小值和最大值
输入样例:
3
0 1 2 3 4
1 -2 1 -5 5
1 -3 1 -5 5
输出样例:
5 6
0 36
-1 41
#include <bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define PII pair<int, int>
using namespace std;
void solve() {
ll a, b, c, d, e, l, r, q1, q2, p1, p2;
ll minn, maxx;
maxx = -1000000000000000000;
minn = 1000000000000000000;
cin >> a >> b >> c >> d >> e;
if (a == 0) {
l = b * d + c;
r = b * e + c;
minn = min(minn, l);
minn = min(minn, r);
maxx = max(maxx, l);
maxx = max(maxx, r);
cout << (ll) minn << " " << (ll) maxx << endl;
return;
}
l = d * d * a + d * b + c;
r = e * e * a + e * b + c;
q1 = ceil(-(b / (2.0 * a)));
q2 = floor(-(b / (2.0 * a)));
p1 = q1 * q1 * a + q1 * b + c;
p2 = q2 * q2 * a + q2 * b + c;
maxx = max(maxx, l);
maxx = max(maxx, r);
minn = min(minn, l);
minn = min(minn, r);
if (q1 >= d && q1 <= e) {
maxx = max(maxx, p1);
minn = min(minn, p1);
}
if (q2 >= d && q2 <= e) {
maxx = max(maxx, p2);
minn = min(minn, p2);
}
cout << (ll) minn << " " << (ll) maxx << endl;
}
signed main() {
int t = 1;
cin >> t;
while (t--) {
solve();
}
return 0;
}
E题 二进制
这是一个关于二进制的问题。
给定一个正整数x,你需要找到一个最小的正整数y,满足x≤y,y在二进制表示下1的个数为偶数对于第二个条件。
例如:4的二进制表达是(100) 2,不满足。
5的二进制表达是(101) 2 ,满足。
输入格式:
第一行输入一个正整数T(1≤T≤10^5 )代表询问的个数。对于每组询问,输入一行一个正整数x(1≤x≤10 ^9)代表一个询问。
输出格式:
输出T行每行一个数代表答案
输入样例:
3
2
5
6
输出样例:
3
5
6
#include <bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define PII pair<int, int>
using namespace std;
void solve() {
long n, m, count;
n = m = count = 0;
cin >> n;
m = n;
while (m > 0) {
if ((m & 1) == 1) {
count++;
}
m >>= 1;
}
if (count % 2 == 0) {
cout << n << endl;
} else {
m = n + 1;
count = 0;
while (m > 0) {
if ((m & 1) == 1) {
count++;
}
m >>= 1;
}
if (count % 2 == 0) {
cout << n + 1 << endl;
} else {
cout << n + 2 << endl;
}
}
}
signed main() {
int t = 1;
cin >> t;
while (t--) {
solve();
}
return 0;
}
H题 修复括号序列
一个合法括号序列的定义如下:
空序列是合法括号序列
若 A 是合法括号序列,则 (A) 也是合法括号序列;
若 A 和 B 都是合法括号序列,则 AB 也是合法括号序列。
例如))和((()都是不合法括号序列,而(),(())和()()都是合法括号序列。
爱丽丝画了一个括号序列,但是因为她太粗心了,所以她画出的序列不一定是合法序列。
爱丽丝想要让序列变成合法序列,她可以对序列进行修改。
每一次修改操作,爱丽丝可以选择任意一个位置,将这个位置的(变成)或者将)变成(。
爱丽丝想要知道是否能通过不超过1次修改操作使序列成为合法括号序列。
输入格式:
第一行输入1个整数n(1≤n≤10^5)。表示括号序列的长度。
第二行输入一个长度为n的字符串s。字符串仅包含(和)两种字符。
输出格式:
输出仅一行。若能通过不超过1次修改操作使序列成为合法括号序列,输出"Yes"(不需要输出引号),否则输出"No"(不需要输出引号)。
输入样例:
4
()()
输出样例:
Yes
#include <bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define PII pair<int, int>
using namespace std;
void solve() {
int n, ans = 0;
string s;
bool ok = false;
cin >> n >> s;
if (n%2==1) {
cout << "No" << endl;
return;
}
for (int i = 0; i < s.size(); ++i) {
if (s[i]=='(') {
ans++;
} else{
ans--;
}
if (ans<0) {
if (!ok) {
ok = true;
ans+=2;
} else{
cout << "No" << endl;
return;
}
}
}
if (!ok && (ans ==0 || ans==2)) {
cout << "Yes" << endl;
return;
}
if (ans==0) {
cout << "Yes" << endl;
} else{
cout << "No" << endl;
}
}
signed main() {
int t = 1;
// cin >> t;
while (t--) {
solve();
}
return 0;
}
I题 石子游戏
爱丽丝和鲍勃正在玩游戏。
有一堆石子,这堆里最初有N个石子。
游戏按照以下规则进行:
第1轮,爱丽丝可以从石子堆中取走不超过1个石子,但不能一个石子都不取。
第2轮,鲍勃可以从石子堆中取走不超过2个石子,但不能一个石子都不取。
第3轮,爱丽丝可以从石子堆中取走不超过3个石子,但不能一个石子都不取。
第4轮,鲍勃可以从石子堆中取走不超过4个石子,但不能一个石子都不取。
…
第i轮,轮到的玩家可以从石子堆中取走不超过i个石子,但不能一个石子都不取。
当某个玩家取走石子堆中的最后一个石子时,该玩家获得胜利。假设爱丽丝和鲍勃都会遵循最优策略,那么谁会胜利?
输入格式:
第一行输入1个整数T(1≤T≤10 ^5)。表示询问个数。
接下来T行,每行一个整数N(1≤N≤10 ^18),表示这局的石堆有N个石子。
输出格式:
输出T行代表每个询问的答案。若爱丽丝胜利,输出"Alice"(不需要输出引号),否则输出"Bob"(不需要输出引号)。
输入样例:
3
1
2
4
输出样例:
Alice
Bob
Alice
N=4时,第1轮爱丽丝取走一个,第2轮无论鲍勃取走一个或者两个,第3轮爱丽丝都能把剩余的取完。
#include <bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define PII pair<int, int>
using namespace std;
//r^2+r
void solve() {
ll n;
cin >> n;
ll a,b;
a = sqrt(n);
b = a*a+a;
if (n>=a && n<b) {
cout << "Alice" << endl;
} else{
cout << "Bob" << endl;
}
}
signed main() {
int t = 1;
cin >> t;
while (t--) {
solve();
}
return 0;
}
J题 密码
爱丽丝发现了一个宝箱,但是打开宝箱需要破解若干组密码。
每组密码都是一对数字(p,q),同时宝箱会给出两个数字A,B作为提示,爱丽丝需要找到所有满足以下条件的(p,q)。
p,q均为质数。
A×p+B×q 是p×q的倍数。
由于满足条件的解有很多,你只需要算出有多少对满足条件的(p,q)。
输入格式:
第一行输入1个整数T(1≤T≤1000)表示询问个数。
接下来T行,每行输入两个整数A,B(1≤A,B≤10^12)表示一个询问。
输出格式:
对于每个询问输出一行一个整数,表示答案。
输入样例:
3
2 3
3 7
10 8
输出样例:
2
3
3
A=2,B=3时,(p,q)可能的两个解是(3,2)和(5,5).
#include <bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define PII pair<int, int>
using namespace std;
bool vis[10000010];
int pri[10000010];
int idx = 0;
void solve() {
ll a, b, c;
cin >> a >> b;
c = a + b;
vector<int> st;
for (int i = 0; pri[i] <= c / pri[i]; i++) {
if (c % pri[i] == 0) {
st.push_back(pri[i]);
}
while (c % pri[i] == 0) {
c /= pri[i];
}
}
if (c > 1) {
if (c >= 1000000000)
st.push_back(-1);
else
st.push_back(c);
}
set<int> aa;
for (int i = 0; pri[i] <= a / pri[i]; i++) {
if (a % pri[i] == 0) {
aa.insert(pri[i]);
}
while (a % pri[i] == 0) {
a /= pri[i];
}
}
if (a > 1) {
if (c >= 1000000000) {
if (a == c)
aa.insert(-1);
else
aa.insert(-2);
} else
aa.insert(a);
}
set<int> bb;
for (int i = 0; pri[i] <= b / pri[i]; i++) {
if (b % pri[i] == 0) {
bb.insert(pri[i]);
}
while (b % pri[i] == 0) {
b /= pri[i];
}
}
if (b > 1) {
if (c >= 1000000000) {
if (b == c)
bb.insert(-1);
else if (a == b)
bb.insert(-2);
else
bb.insert(-3);
} else
bb.insert(b);
}
ll ans = aa.size() * bb.size() + st.size();
for (int i = 0; i < st.size(); i++) {
if (aa.count(st[i]) && bb.count(st[i]))
ans--;
}
cout << ans << "\n";
}
int main() {
set<PII > st;
for (int i = 2; i <= 10000000; i++) {
if (!vis[i])
pri[idx++] = i;
for (int j = 0; pri[j] <= 10000000 / i; j++) {
vis[i * pri[j]] = true;
if (i % pri[j] == 0)
break;
}
}
int t = 1;
cin >> t;
while (t--) {
solve();
}
return 0;
}