吐槽一下出题人英语还是要好好学一下,然后就是别题意全从问答拿,还有数据不知道什么鬼
A
B
bfs就行,题意问答拿
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iomanip>
using namespace std;
int const N = 200005;
bool isans[N], ismon[N], is1[N], col[N];
double ans[N];
int num[N];
int n, m, K;
struct edge {
int y, next;
} e[N << 1];
int last[N], ne;
void addedge(int x, int y) {
e[++ne].y = y;
e[ne].next = last[x];
last[x] = ne;
}
int g[N], cnt;
void bfs(int x) {
cnt = 0;
queue<int> q;
q.push(x);
col[x] = 1;
while (q.empty() == 0) {
int now = q.front();
q.pop();
g[++cnt] = now;
for (int i = last[now]; i; i = e[i].next)
if (col[e[i].y] == 0 && ismon[e[i].y] == 0) {
q.push(e[i].y);
col[e[i].y] = 1;
}
}
for (int i = 1; i <= cnt; ++i)
num[g[i]] = cnt;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d%d", &n, &m, &K);
for (int i = 1; i <= n; ++i) {
last[i] = 0;
ismon[i] = 0;
col[i] = 0;
isans[i] = 0;
is1[i] = 0;
ans[i] = 0;
num[i] = 0;
}
ne = 0;
for (int i = 1; i <= m; ++i) {
int x, y;
scanf("%d%d", &x, &y);
addedge(x, y);
addedge(y, x);
}
for (int i = 1; i <= K; ++i) {
int x;
scanf("%d",&x);
ismon[x] = 1;
}
bfs(1);
for (int i = 1; i <= cnt; ++i) {
is1[g[i]] = 1;
for (int j = last[g[i]]; j != 0; j = e[j].next)
if (ismon[e[j].y])
isans[e[j].y] = 1;
}
int ans1 = cnt;
for (int i = 1; i <= n; ++i)
if (col[i] == 0 && ismon[i] == 0)
bfs(i);
for (int i = 1; i <= n; ++i)
if (isans[i]) {
int du = 0;
for (int j = last[i]; j; j = e[j].next)
//if (ismon[e[j].y] == 0)
++du;
for (int j = last[i]; j; j = e[j].next)
//if (ismon[e[j].y] == 0)
{
int s = ans1;
if (is1[e[j].y] == 0)
s += num[e[j].y];
ans[i] += 1.0 * s / du;
}
}
double anss = 0;
for (int i = 1; i <= n; ++i)
anss = max(anss, ans[i]);
cout << fixed << setprecision(10) << anss << '\n';
}
}
C
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
using ll = long long;
int const N = 10005;
ll f[N];
int n, m;
int main() {
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = 1; i <= 1e4; ++i)
f[i] = 1e18;
f[0] = 0;
for (int i = 1; i <= n; ++i) {
int x, y;
scanf("%d%d", &x, &y);
for (int j = y; j <= 1e4; ++j)
f[j] = min(f[j], f[j - y] + x);
}
ll ans = 1e18, ans2 = -1;
for (int i = m; i <= 1e4; ++i)
if (f[i] <= ans) {
ans = f[i];
ans2 = i;
}
cout << ans << ' ' << ans2 << '\n';
}
}
D
树D合并一下就行。
#include <array>
#include <iostream>
#include <algorithm>
#include <cstdint>
using i64 = int64_t;
const i64 MOD = 1000000007;
struct Graph {
struct E {
int to, w;
};
using Arr = std::array<int, 3>;
int n;
std::vector<std::vector<E>> es;
std::vector<Arr> cnt;
std::vector<Arr> sum;
Arr ans;
Graph(int n): n(n), es(n), cnt(n), sum(n), ans() {}
void adde(int a, int b, int w) {
es[a].push_back({ b, w });
}
void dfs(int c, int fa) {
cnt[c][0] = (cnt[c][0] + 1) % MOD;
// sum[c][0] += 0;
for (auto &nxt: es[c])
if (nxt.to != fa) {
dfs(nxt.to, c);
Arr ccnt = {}, csum = {};
for (int i = 0; i < 3; ++i) {
int idx = (i + nxt.w) % 3;
ccnt[idx] = cnt[nxt.to][i];
csum[idx] = ((i64)cnt[nxt.to][i] * nxt.w + sum[nxt.to][i]) % MOD;
}
//std::cerr << "cur " << ccnt[0] << ' ' << ccnt[1] << ' ' << ccnt[2] << '\n';
//std::cerr << "sum " << csum[0] << ' ' << csum[1] << ' ' << csum[2] << '\n';
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j) {
int tg = (i + j) % 3;
ans[tg] = (ans[tg] + (i64)sum[c][i] * ccnt[j] + (i64)cnt[c][i] * csum[j]) % MOD;
}
//std::cerr << "ans " << ans[0] << ' ' << ans[1] << ' ' << ans[2] << '\n';
for (int i = 0; i < 3; ++i) {
cnt[c][i] = (cnt[c][i] + ccnt[i]) % MOD;
sum[c][i] = (sum[c][i] + csum[i]) % MOD;
//std::cerr << "mgcur " << cnt[c][0] << ' ' << cnt[c][1] << ' ' << cnt[c][2] << '\n';
//std::cerr << "mgsum " << sum[c][0] << ' ' << sum[c][1] << ' ' << sum[c][2] << '\n';
}
}
}
};
int main () {
std::ios::sync_with_stdio(false);
int n;
while (std::cin >> n) {
Graph g { n };
for (int i = 0; i < n - 1; ++i) {
int a, b, w;
std::cin >> a >> b >> w;
g.adde(a, b, w);
g.adde(b, a, w);
}
g.dfs(0, 0);
auto ans = g.ans;
for (int i = 0; i < 3; ++i) {
ans[i] = ans[i] * 2 % MOD;
std::cout << ans[i];
if (i != 2)
std::cout << ' ';
}
std::cout << '\n';
}
return 0;
}
E
F
这个F真的把我们搞飞了,以为二分套二分不能过,我们就直接二分上界,但是不是所有大于这个上界的数直接挪到下界之下就行,要尽可能的把多一点的数小于上界,让下界更大才行。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <utility>
#include <cstdlib>
#include <cstring>
#include <cassert>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
int const N = 500005;
int a[N], n, m;
int aver;
pll chk(ll lim) {
ll sum = 0;
for (int i = 1; i <= n; ++i)
if (a[i] >= lim)
sum += a[i] - lim;
if (sum < m)
for (int i = 1; i < n; ++i)
if (a[i] >= lim && sum < m)
++sum;
ll inf = 1e18;
ll s = 0;
for (int i = 1; i <= n; ++i) {
s += a[i];
if (1ll * a[i] * i - s > sum) {
ll t = 1ll * a[i] * i - s;
t = a[i] - (t - sum + i - 2) / (i - 1);
return { lim - t, sum };
}
}
ll t = 1ll * n * a[n] - s;
return { lim - (a[n] + (sum - t) / n), sum };
}
int main() {
//ios::sync_with_stdio(0);
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
sort(a + 1, a + n + 1);
ll l = *min_element(a + 1, a + n + 1);
ll r = *max_element(a + 1, a + n + 1);
ll ans = 1e18;
ll sum = 0;
for (int i = 1; i <= n; ++i)
sum += a[i];
ll flag = sum % n ? 1 : 0, ttt = 1e18;
/*
for (int i = l; i <= r; ++i) {
cerr << i << ' ' << chk(i).first << ' ' << chk(i).second << '\n';
if (chk(i).second <= m)
ttt = min(ttt, chk(i).first);
}
ttt = max(ttt, flag);
*/
while (l <= r) {
ll mid = (l + r) >> 1;
auto t = chk(mid);
t.first = max(t.first, flag);
//cerr << l << ' ' << r << ' ' << mid << ' ' << t.first << ' ' << t.second << ' '<< m << '\n';
if (t.second <= m) {
ans = min(ans, t.first);
r = mid - 1;
} else
l = mid + 1;
}
//cerr << ttt << ' ' << ans << '\n';
//assert(ans == ttt);
cout << ans << '\n';
}
}
G
这种题真的没什么意思,泰勒展开算一下,后面的项就小于精度了。
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 1000010;
const int CNT = 32;
char s[maxn];
double tbl[CNT];
int main() {
double x = 5.0 / 3.0;
for (int i = 1; i < CNT; ++i) {
tbl[i] = x;
x = (3.0 + 5.0 * x) / (2.0 + 3.0 * x);
//std::cerr << std::fixed << std::setprecision(16) << x << '\n';
}
int T;
cin >> T;
while(T--) {
double a;
cin >> s >> a;
int n = strlen(s);
int nn = 0;
for (int i = 0; i < n; ++i) {
nn = nn * 10 + (s[i] - '0');
if (nn >= CNT) {
nn = CNT - 1;
break;
}
}
double ans = tbl[nn] * a;
std::cout << std::fixed << std::setprecision(10) << ans << '\n';
}
}
H
模拟就行。
#include <iostream>
#include <string>
#include <string.h>
#include <assert.h>
#include <algorithm>
using namespace std;
const int maxn = 100010;
struct Person {
string name;
int card[20];
int rk[10];
bool operator < (const Person& b) const {
for(int i = 0;i < 5;i++) {
if(rk[i] != b.rk[i]) return rk[i] > b.rk[i];
}
return name < b.name;
}
void read() {
memset(rk,0,sizeof(rk));
cin >> name;
char s[20];
cin >> s;
int n = strlen(s);
int cnt = 0;
for(int i = 0;i < n;i++) {
if(s[i] == '1') {
card[cnt++] = 10;
i++;
}
else if(s[i] == 'A') {
card[cnt++] = 1;
}
else if(s[i] == 'J') {
card[cnt++] = 11;
}
else if(s[i] == 'Q') {
card[cnt++] = 12;
}
else if(s[i] == 'K') {
card[cnt++] = 13;
}
else {
card[cnt++] = s[i]-'0';
}
}
sort(card,card+5);
}
}ps[maxn];
int RStr(Person& p,const int* c) {
if(c[0] == 1 && c[1] == 10 && c[2] == 11 && c[3] == 12 && c[4] == 13) {
p.rk[0] = 10;
return 1;
}
return 0;
}
int straight(Person& p,const int* c) {
for(int i = 1;i < 5;i++) if(c[i] != c[i-1]+1) {
return 0;
}
p.rk[0] = 9;
p.rk[1] = c[4];
return 1;
}
int four(Person& p,const int* c) {
int flg = c[0];
for(int i = 1;i < 4;i++) if(c[i] != c[i-1]) flg = 0;
if(flg) {
p.rk[0] = 8;
p.rk[1] = flg;
p.rk[2] = c[4];
return 1;
}
flg = c[4];
for(int i = 2;i < 5;i++) if(c[i] != c[i-1]) flg = 0;
if(flg) {
p.rk[0] = 8;
p.rk[1] = flg;
p.rk[2] = c[0];
return 1;
}
return 0;
}
int full(Person& p,const int* c) {
int flg = c[0];
for(int i = 1;i < 3;i++) if(c[i] != c[i-1]) flg = 0;
if(flg && c[3] == c[4]) {
p.rk[0] = 7;
p.rk[1] = flg;
p.rk[2] = c[3];
return 1;
}
flg = c[4];
for(int i = 3;i < 5;i++) if(c[i] != c[i-1]) flg = 0;
if(flg && c[0] == c[1]) {
p.rk[0] = 7;
p.rk[1] = flg;
p.rk[2] = c[0];
return 1;
}
return 0;
}
int three(Person& p,const int* c) {
int flg = c[0];
for(int i = 1;i < 3;i++) if(c[i] != c[i-1]) flg = 0;
if(flg) {
p.rk[0] = 6;
p.rk[1] = flg;
p.rk[2] = c[3]+c[4];
return 1;
}
flg = c[1];
for(int i = 2;i < 4;i++) if(c[i] != c[i-1]) flg = 0;
if(flg) {
p.rk[0] = 6;
p.rk[1] = flg;
p.rk[2] = c[0]+c[4];
return 1;
}
flg = c[4];
for(int i = 3;i < 5;i++) if(c[i] != c[i-1]) flg = 0;
if(flg) {
p.rk[0] = 6;
p.rk[1] = flg;
p.rk[2] = c[0]+c[1];
return 1;
}
return 0;
}
int twoPair(Person& p,const int* c) {
int p1 = 0,p2 = 0;
for(int i = 1;i < 5;i++) {
if(c[i] == c[i-1]) {
if(p1) p2 = c[i];
else p1 = c[i];
}
}
if(p1 && p2) {
p.rk[0] = 5;
p.rk[1] = max(p1,p2);
p.rk[2] = min(p1,p2);
if(c[0] != c[1]) p.rk[3] = c[0];
else if(c[4] != c[3]) p.rk[3] = c[4];
else p.rk[3] = c[2];
return 1;
}
return 0;
}
int Pair(Person& p,const int* c) {
for(int i = 1;i < 5;i++) {
if(c[i] == c[i-1]) {
p.rk[0] = 4;
p.rk[1] = c[i];
for(int j = 0;j < 5;j++) {
if(j != i && j != i-1) p.rk[2] += c[j];
}
return 1;
}
}
return 0;
}
void getRk(Person& p) {
if(RStr(p,p.card)) return ;
else if(straight(p,p.card)) return;
else if(four(p,p.card)) return;
else if(full(p,p.card)) return;
else if(three(p,p.card)) return;
else if(twoPair(p,p.card)) return;
else if(Pair(p,p.card)) return;
else {
p.rk[0] = 3;
for(int i = 0;i < 5;i++) {
p.rk[1] += p.card[i];
cerr << p.card[i] << endl;
}
}
}
int main() {
int n;
while(cin >> n) {
for(int i = 0;i < n;i++) {
ps[i].read();
getRk(ps[i]);
}
sort(ps,ps+n);
for(int i = 0;i < n;i++) {
cout << ps[i].name << endl;
}
}
return 0;
}
I
J
gg我用之前的比赛账号交的题,然后账号注销了,没有拿到代码。
不过很简单公不公布代码都行。答案就是
1
X
+
1
+
1
X
+
2
+
.
.
.
+
1
n
\frac{1}{X+1}+\frac{1}{X+2}+...+\frac{1}{n}
X+11+X+21+...+n1
然后再用
1
1
1减去就行
不过要注意到
X
≥
n
2
X \geq \frac{n}{2}
X≥2n
于是就反面考虑。
分母显然是
n
!
n!
n!
分子显然就是
n
!
−
∑
i
=
X
+
1
n
C
(
n
,
i
)
(
i
−
1
)
!
(
n
−
i
)
!
n! - \sum_{i = X+1}^n C(n, i) (i - 1)! (n - i)!
n!−i=X+1∑nC(n,i)(i−1)!(n−i)!
化简就得到答案了。只要知道轮换的个数是
(
n
−
1
)
!
(n-1)!
(n−1)!,置换的个数是
n
!
n!
n!就能做
K
理解的题意和出题人想表达的不同,但是比赛时一发过了,不想理会了。出题人英语什么鬼啊?数据又是很么鬼啊?
出于上诉原因不放代码出来了。