2020牛客暑期多校训练营(第五场)
F. DPS
题目大意
有 n n n个玩家,每个玩家对敌方的总伤害为 d i d_{i} di,定义其贡献 s = ⌈ 50 × d i m a x j = 1 n d j ⌉ s=⌈50\times\frac{d_{i}}{max_{j=1}^{n}d_{j}}⌉ s=⌈50×maxj=1ndjdi⌉,按照指定格式打印 s s s
解题思路
纯模拟就行了,注意会爆 l o n g l o n g longlong longlong
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 110;
ll a[maxn];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
ll Max = 0;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
Max = max(Max, a[i]);
}
for(int i = 1; i <= n; ++i) {
ll cnt = (50 * a[i] + Max - 1) / Max;
cout << '+';
for(int j = 1; j <= cnt; ++j) cout << '-';
cout << "+\n";
cout << '|';
for(int j = 1; j < cnt; ++j) cout << ' ';
if(a[i] == Max) cout << '*';
else if(a[i]) cout << ' ';
cout << '|';
cout << a[i] <<'\n';
cout << '+';
for(int j = 1; j <= cnt; ++j) cout << '-';
cout << "+\n";
}
return 0;
}
I. Hard Math Problem
题目大意
在一块空地上可以放置三种类型 G G G, H H H, E E E,其中 H H H必须和至少一个 G G G和至少一个 E E E相邻,定义 f ( n , m ) f(n,m) f(n,m)表示在 n × m n\times m n×m大小的空地上能够放置 H H H的最大数量问你 l i m n → ∞ l i m m → ∞ f ( n , m ) n × m lim_{n\to\infty}lim_{m\to\infty}\frac{f(n,m)}{n\times m} limn→∞limm→∞n×mf(n,m)是多少
解题思路
.
.
.
...
...
.
.
.
H
E
H
H
E
H
H
E
H
H
E
H
.
.
.
...HEHHEHHEHHEH...
...HEHHEHHEHHEH...
.
.
.
G
H
H
G
H
H
G
H
H
G
H
H
.
.
.
...GHHGHHGHHGHH...
...GHHGHHGHHGHH...
.
.
.
H
H
E
H
H
E
H
H
E
H
H
E
.
.
.
...HHEHHEHHEHHE...
...HHEHHEHHEHHE...
.
.
.
H
G
H
H
G
H
H
G
H
H
G
H
.
.
.
...HGHHGHHGHHGH...
...HGHHGHHGHHGH...
.
.
.
E
H
H
E
H
H
E
H
H
E
H
H
.
.
.
...EHHEHHEHHEHH...
...EHHEHHEHHEHH...
.
.
.
...
...
所以答案是
2
3
\frac{2}{3}
32
AC代码
#include <bits/stdc++.h>
using namespace std;
int main() {
printf("0.666667");
return 0;
}
E. Bogo Sort
题目大意
给你某一个 1 ∽ n 1\backsim n 1∽n的排列 p p p,假设有一个 1 ∽ n 1\backsim n 1∽n的排列 a a a,不停地使得 a [ i ] = a [ p [ i ] ] a[i]=a[p[i]] a[i]=a[p[i]],问你有多少种排列经过如上变换最终会变成升序数组
解题思路
置换群求最小置换次数
定义
∗
*
∗运算为
a
[
i
]
=
a
[
p
[
i
]
]
a[i]=a[p[i]]
a[i]=a[p[i]]
假设
a
1
k
1
=
a
1
a_{1}^{k_{1}}=a_{1}
a1k1=a1
a
2
k
2
=
a
2
a_{2}^{k_{2}}=a_{2}
a2k2=a2
a
3
k
3
=
a
3
a_{3}^{k_{3}}=a_{3}
a3k3=a3
.
.
.
...
...
那么就是所有置换群中的最大次数(
k
i
k_{i}
ki)求
l
c
m
lcm
lcm
需要用到 J a v a Java Java大数
AC代码
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
static int maxn = (int)1e5 + 10;
static int[] a = new int[maxn];
static boolean[] vis = new boolean[maxn];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
BigInteger res = new BigInteger("1");
BigInteger Mod = new BigInteger("1");
for(int i = 1; i <= n; ++i) {
a[i] = sc.nextInt();
Mod = Mod.multiply(BigInteger.valueOf(10));
}
for(int i = 1; i <= n; ++i) {
if(vis[i]) continue;
int cnt = 1, cur = i;
vis[cur] = true;
while(!vis[a[cur]]) {
++cnt;
cur = a[cur];
vis[cur] = true;
}
BigInteger Gcd = res.gcd(BigInteger.valueOf(cnt));
res = res.multiply(BigInteger.valueOf(cnt).divide(Gcd));
}
System.out.println(res.mod(Mod));
sc.close();
}
}
D. Drop Voicing
题目大意
给你一个 1 ∽ n 1\backsim n 1∽n的排列 p p p,有两种操作:
- 将 p n − 1 p_{n-1} pn−1移动至头部
- 将
p
1
p_{1}
p1移动到尾部
其中每次操作可以进行无数次操作一或操作二,问你操作一的最小操作次数
解题思路
操作二相当于将这个数组无限旋转,即将链状数组变成环状数组,操作一相当于将任意一个数提前到任意位置,那么我们固定某一个最长上升子序列相对位置不动,持续移动其他数字即可,那么答案就是 n n n减去环状数组的最大 L I S LIS LIS,时间复杂度 O ( n 2 l o g 2 n ) O(n^{2}log_{2}^{n}) O(n2log2n)
AC代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 510;
int a[maxn], b[maxn], dp[maxn];
int LIS(int n) {
memset(dp, 0, sizeof(int) * n);
int cnt = 1;
dp[cnt] = b[1];
for(int i = 2; i <= n; ++i) {
if(b[i] > dp[cnt]) dp[++cnt] = b[i];
else dp[lower_bound(dp + 1, dp + cnt + 1, b[i]) - dp] = b[i];
}
return cnt;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
}
int res = INT_MAX;
for(int i = 0; i < n; ++i) {
for(int j = 1; j <= n; ++j) {
int index = (j + i) % n;
if(!index) index = n;
b[j] = a[index];
}
res = min(res, n - LIS(n));
}
cout << res << '\n';
return 0;
}