比赛总结
暑期第一次打牛客团队赛,居然运气不错的就中奖了。不过这次的题总体都不难,差1题就可以AK了呢。
还是来总结下吧,先附上算法大纲。
- easy:B(模拟)、C(高精度)、G(排序)、H(BF)、I(规律题)、J(简单DP)、L(打表BF)
- mid:K(floyd传递闭包)、D(复杂模拟)、F(最短路+二分)
- hard:E(二分+并查集)、A(树形DP求最小支配集合)
其中蒟蒻的我写了BCGHIF(果然我只配写简单题)
B-iCow
题意
有N(1 <= N <= 1,000)首歌曲,按照1-N编号。
- 第i首曲子有一个初始权值R_i(1 <= R_i <= 10,000)。
- 当一首曲子播放完毕,接下来播放的将是所有曲子中权值最大的那首(如果有两首或多首曲子的权值相同,那么这些曲子中编号最小的那首会被选中)。
- 一首曲子在播放结束后,它的权值会被平均地分给其他N-1首曲子,它本身的权值清零。
如果一首曲子的权值无法被平均分配(也就是说,无法被N-1整除),那么被N-1除的余数部分将会以1为单位,顺次分配给排名靠前的曲子(也就是说,顺序为曲目1、曲目2...依次下去。当然,刚播放过的那首曲子需要被跳过),直到多出的部分被分配完。
在选定的下一首曲子播放完毕后,这个算法再次被执行,调整曲子的权值,并选出再接下来播放的曲目。
请你计算一下,按FJ的算法,最先播放的T(1 <= T <= 1000)首曲子分别是哪些。
分析
数据不大,简单模拟题。
AC代码
#include <bits/stdc++.h>
#define FAST_IO std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)
#define pause system("pause")
using namespace std;
typedef long long ll;
typedef unsigned int UINT;
typedef unsigned long long ull;
int const maxn = 1000 + 10;
int a[maxn];
int main(void) {
FAST_IO;
int n, t;
cin >> n >> t;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 0; i < t; i++) {
int pos = max_element(a + 1, a + 1 + n) - a;
cout << pos << endl;
int x = a[pos] % (n - 1);
int s = a[pos] / (n - 1);
a[pos]= 0;
for (int i = 1; i <= n; i++) {
if (i == pos) continue;
a[i] += s;
if (x) {
a[i]++;
x--;
}
}
}
// pause;
return 0;
} C-阶乘之和
分析
python大法真好。
AC代码
n = int(input())
def fact(x):
s = 1
for i in range(1, x + 1):
s *= i
return s
sum = 0
for i in range(1, n + 1):
sum += fact(i)
if sum == 0:
sum += 1
print(sum) G-Election Time
题意
一场比赛,规则有两轮,再第一轮中选出前k个牛,再在这k只牛中选取第二轮中票数最多的牛,输出它的编号。
分析
进行两次排序就行。
AC代码
#include <bits/stdc++.h>
#define FAST_IO std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)
#define pause system("pause")
using namespace std;
typedef long long ll;
typedef unsigned int UINT;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
int const maxn = 50000 + 10;
struct node {
ll a, b;
int x;
};
node a[maxn];
int main(void) {
FAST_IO;
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i].a >> a[i].b;
a[i].x = i;
}
sort(a + 1 , a + 1 + k, [](const node &x, const node &y){
return x.a > y.a;
});
sort(a + 1 , a + 1 + k, [](const node &x, const node &y){
return x.b > y.b;
});
cout << a[1].x << endl;
// pause;
return 0;
} H-Costume Party
分析
真的暴力就行了emmm.
AC代码
#include <bits/stdc++.h>
#define FAST_IO std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)
#define pause system("pause")
using namespace std;
typedef long long ll;
typedef unsigned int UINT;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
int const maxn = 50000 + 10;
int a[maxn];
int main(void) {
FAST_IO;
int num = 0;
int n, s;
cin >> n >> s;
for (int i = 0; i < n;i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
for (int j = i + 1;j < n; j++) {
if (a[i] + a[j] <= s)
++num;
}
}
cout << num << endl;
// pause;
return 0;
} I-Cantor表
分析
数表提示我们按照斜线分类。第1条斜线有1个数,第2条有2个数,第3条有3个数……第k条有k个数。这样,前k条斜线一共有个数。
第n项在哪条斜线上呢?只要找到一个最小的k,使得,那么第n项就是第k条斜线上倒数第S-n+1个数(最后一个元素是倒数第1个元素,而不是倒数第0个元素)。
而k的奇偶决定着第k条斜线上数的顺序:若k是奇数,第k条斜线上倒数第i个元素是;若k是偶数,第k条斜线上倒数第i个元素是
。
AC代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,h=1;
cin>>n;
while(n-h>0)
{
n=n-h;
h++;
}
if(!h%2)
cout<<n<<"/"<<h+1-n<<endl;
else
cout<<h+1-n<<"/"<<n<<endl;
return 0;
} F-Telephone Lines
题意
找出1-n的通路中,第K+1大的路径权值最小的值。
分析
经典的二分+最短路解法。由于答案具有单调性,所以可以对其二分答案,若路径i的权值大于mid则为1,否则为0。然后进行找1到n的最短路。那么跑完最短路之后,由于小于mid的边权值均为0,1-n最短路的值就是路径上所有比mid大的边的总数。
AC代码
#include <bits/stdc++.h>
typedef long long ll;
typedef unsigned int UINT;
typedef unsigned long long ull;
typedef unsigned long long ull;
#define FAST_IO std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)
#define PAUSE system("pause")
using namespace std;
int const maxn = 10000 + 10;
struct Node {
int v, w, next;
}e[maxn << 1];
struct node {
int u;
int w;
node(int const &u = 0, int const &w = 0) :
u(u), w(w) {}
bool operator<(const node &p) const{
return w > p.w;
}
};
int head[maxn], vis[maxn];
int dis[maxn];
int cnt = 0;
int n, m, k;
void add(int u, int v, int w) {
e[cnt].v = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt++;
}
void dijkstra(int mid) {
priority_queue<node> q;
for (int i = 1; i <= n; i++) {
dis[i] = INT_MAX;
vis[i] = 0;
}
dis[1] = 0;
q.push(node(1, dis[1]));
while (!q.empty()) {
int u = q.top().u;
q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
int w = e[i].w > mid ? 1 : 0;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.push(node(v, dis[v]));
}
}
}
}
int main(void) {
FAST_IO;
memset(head, -1, sizeof(head));
cin >> n >> m >> k;
int l = 0, r = -1;
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
r = max(r, w);
add(u, v, w);
add(v, u, w);
}
int mx = r;
while (l < r) {
int mid = (l + r) / 2;
dijkstra(mid);
if (dis[n] <= k) {
r = mid;
} else {
l = mid + 1;
}
}
if (mx == r) {
cout << -1 << endl;
} else {
cout << r << endl;
}
// PAUSE;
return 0;
} 
京公网安备 11010502036488号