第一届ACC(AcWing Cup)全国高校联赛(决赛)
大赛简介:
ACC(AcWing Cup)高校联赛是由AcWing举办的算法比赛,难度与蓝桥杯省赛持平,比赛设立高校团体排行榜和丰厚奖金。
2021年,北京大学AcWing杯程序设计竞赛圆满举行;2022年,AcWing将与更多高校一起培养更多算法人才。
赛制:
ACM赛制,共90分钟,3道题目,每道题目记1分。
每道题目的罚时为AC时刻与比赛开始时刻所经过的时间。
通过题目的非AC提交每次罚时5分钟。
通过题目数相同时,总罚时短的同学排名靠前。
两个闹钟
有两个闹钟。
第一个闹钟会在 b,b+a,b+2a,b+3a,… 时刻响铃。
第二个闹钟会在 d,d+c,d+2c,d+3c,… 时刻响铃。
请计算两个闹钟第一次同时响铃的具体时刻。
输入格式
第一行包含两个整数 a,b。
第二行包含两个整数 c,d。
输出格式
一个整数,表示第一次同时响铃的具体时刻。
如果永远都不可能同时响铃,则输出 −1。
数据范围
所有测试点满足 1≤a,b,c,d≤100。
输入样例1:
20 2
9 19
输出样例1:
82
输入样例2:
2 1
16 12
输出样例2:
-1
第一题做的时候就没想什么,就直接暴力, 没想到直接过了
#include <bits/stdc++.h>
using namespace std;
int a, b, c, d;
int main()
{
cin >> a >> b >> c >> d;
int res = -1;
for(int i = 0; i < 1000 && res == -1; i++)
{
for(int j = 0; j < 1000; j++)
{
if(b - d == i * c - j * a)
{
res = d + c * i;
break;
}
}
}
cout << res << endl;
return 0;
}
这里再附上JAVA代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
long a=sc.nextInt();
long b=sc.nextInt();
long c=sc.nextInt();
long d=sc.nextInt();//输入四个数
long arr[]=new long[103];
long arr2[]=new long[103];//开两个较大的数组
int n=102;
for(int i=1;i<=n;i++){
arr[i]=b;
arr2[i]=d;
b+=a;
d+=c;//将b+a*i和d+c*i分别放进两个数组中
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(arr[i]==arr2[j]){
System.out.println(arr[i]);//遍历两个数组,如果相等就输出。
return;
}
}
}
System.out.println(-1);
}
}
合并石子
小 A 面前有 n 堆石子排成一排,每堆石子的数量从左到右依次为 a1,a2,…,an。
小 B 面前有 m 堆石子排成一排,每堆石子的数量从左到右依次为 b1,b2,…,bm。
两人面前的石子总数相同,即 a1+a2+…+an=b1+b2+…+bm。
每个人都可以对自己面前的石子堆进行任意次合并操作,两个人的操作次数可以不同。
合并操作指将连续的若干堆相邻石子合并为一堆。
请你确定一个最大的整数 k,满足:
小 A 停止所有操作后,面前恰好有 k 堆石子,每堆石子的数量从左到右依次为 a′1,a′2,…,a′k。
小 B 停止所有操作后,面前恰好有 k 堆石子,每堆石子的数量从左到右依次为 b′1,b′2,…,b′k。
对于 1≤i≤k,a′i=b′i 均成立。
输出这个 k 的最大可能值。
输入格式
第一行包含两个整数 n,m。
第二行包含 n 个整数 a1,a2,…,an。
第三行包含 m 个整数 b1,b2,…,bm。
输出格式
一个整数,表示 k 的最大可能值。
数据范围
前三个测试点满足 1≤n,m≤10。
所有测试点满足 1≤n,m≤105,1≤ai,bi≤106,a1+a2+…+an=b1+b2+…+bm≤106。
输入样例1:
7 6
2 5 3 1 11 4 4
7 8 2 4 1 8
输出样例1:
3
输入样例2:
3 3
1 10 100
1 100 10
输出样例2:
2
输入样例3:
1 4
4
1 1 1 1
输出样例3:
1
这道题最开始没读懂题,也就没有思路,后来静下来又慢慢地一个一个字的读题,才发现应该是前缀和和双指针,然后就试了一下。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N],b[N],s1[N],s2[N];
int n , m;
int main()
{
cin >> n >> m;
for(int i = 1 ; i <= n ; i ++)
{
cin >> a[i]; s1[i] = s1[i-1] + a[i];
}
for(int j = 1 ; j <= m ; j ++)
{
cin >> b[j]; s2[j] = s2[j-1] + b[j];
}
int res = 0,i = 1 , j = 1, k = 1 , l = 1;
while(i <= n && j <= m)
{
if(s1[i] - s1[j-1] == s2[k] - s2[l-1])
{
res ++;
i ++ , k ++ ;
j = i;
l = k;
}
else
{
if(s1[i] - s1[j-1] < s2[k] - s2[l-1]) i++;
else k++;
}
}
cout << res ;
return 0;
}
也附上JAVA代码
import java.util.Scanner;
public class Main{
public static void main(String[] args){
int res = 0;
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[]a = new int[n + 1];
int[]b = new int[m + 1];
for(int i = 0; i < n; i++) a[i] = sc.nextInt();
for(int i = 0; i < m; i++) b[i] = sc.nextInt();
int i = 0;
int j = 0;
int c1 = a[0];
int c2 = b[0];
while(i < n || j < m){
if(c1 == c2){
res++;
i++;
j++;
c1 = a[i];
c2 = b[j];
//如果c1小于c2就把c1后面加进来
}else if(c1 < c2){
i++;
c1 += a[i];
//同理就行
}else{
j++;
c2 += b[j];
}
}
System.out.println(res);
}
}
翻转树边
给定一个 n 个节点的树。
节点编号为 1∼n。
树中的 n−1 条边均为单向边。
现在,我们需要选取一个节点作为中心点,并希望从中心点出发可以到达其他所有节点。
但是,由于树中的边均为单向边,所以在选定中心点后,可能无法从中心点出发到达其他所有节点。
为此,我们需要翻转一些边的方向,从而使得所选中心点可以到达其他所有节点。
我们希望选定中心点后,所需翻转方向的边的数量尽可能少。
请你确定哪些点可以选定为中心点,并输出所需的最少翻转边数量。
输入格式
第一行包含整数 n。
接下来 n−1 行,每行包含两个整数 a,b,表示存在一条从 a 到 b 的单向边。
输出格式
第一行输出一个整数,表示所需的最少翻转边数量。
第二行以升序顺序输出所有可选中心点(即所需翻转边数量最少的中心点)的编号。
数据范围
前三个测试点满足 2≤n≤5。
所有测试点满足 2≤n≤2×105,1≤a,b≤n,a≠b。
输入样例1:
3
2 1
2 3
输出样例1:
0
2
输入样例2:
4
1 4
2 4
3 4
输出样例2:
2
1 2 3
第三题我是真的没读懂题,然后看了y总的直播到现在也没明白,先附上y总的代码吧。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200010, M = N * 2;
int n;
int h[N], e[M], w[M], ne[M], idx;
int down[N], up[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
void dfs_down(int u, int from)
{
for (int i = h[u]; ~i; i = ne[i])
{
if (i == (from ^ 1)) continue;
int j = e[i];
dfs_down(j, i);
down[u] += down[j] + w[i];
}
}
void dfs_up(int u, int from)
{
if (from != -1)
{
int fa = e[from ^ 1];
up[u] = up[fa] + down[fa] - down[u] - w[from] + w[from ^ 1];
}
for (int i = h[u]; ~i; i = ne[i])
{
if (i == (from ^ 1)) continue;
int j = e[i];
dfs_up(j, i);
}
}
int main()
{
scanf("%d", &n);
memset(h, -1, sizeof h);
for (int i = 0; i < n - 1; i ++ )
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b, 0);
add(b, a, 1);
}
dfs_down(1, -1);
dfs_up(1, -1);
int res = N;
for (int i = 1; i <= n; i ++ )
res = min(res, down[i] + up[i]);
printf("%d\n", res);
for (int i = 1; i <= n; i ++ )
if (down[i] + up[i] == res)
printf("%d ", i);
return 0;
}
作者:yxc
链接:https://www.acwing.com/activity/content/code/content/3032110/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
小羊还是差得远呢,小羊加油吧。