AtCoder Beginner Contest 227
Posted 佐鼬Jun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 227相关的知识,希望对你有一定的参考价值。
C - ABC conjecture
题意:
给定一个 N N N,现在问有多少个三元组 ( A , B , C ) (A,B,C) (A,B,C), A ≤ B ≤ C A≤B≤C A≤B≤C , A B C ≤ N ABC≤N ABC≤N
思路:
直接暴力枚举,时间复杂度 O ( N 2 3 ) O(N^\\frac23) O(N32),枚举A和B然后算出有多少个C
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int s[N];
#define ll long long
int main()
ll n;
cin >> n;
ll res = 0;
for (ll i = 1; i * i * i <= n; i++)
for (ll j = i; i * j * j <= n; j++)
res += n / i / j - j + 1;
cout << res << endl;
D - Project Planning.
题意:
给一个长度为 N N N的数列, A 1 . . . . A N A_1....A_N A1....AN, A i ≥ 1 A_i≥1 Ai≥1,现在每次选 K K K个数减去 1 1 1,每个数只能被减到 0 0 0,问整个数列最多能操作几次
思路:
假设可以操作
P
P
P次,现在令
s
u
m
=
sum=
sum=
∑
i
=
1
n
m
i
n
(
P
,
A
i
)
\\sum_i=1^n min(P,A_i)\\qquad
∑i=1nmin(P,Ai),
如果
P
×
K
>
s
u
m
P×K>sum
P×K>sum,那么很明显是不够减的,所以一定不成立
可以假设当
P
×
K
≤
s
u
m
P×K≤sum
P×K≤sum时,我们可以操作
P
P
P次
每次操作的策略始终都是拿最大的
K
K
K个数
假设
≥
P
≥P
≥P的个数为
n
u
m
num
num
1. 如果
n
u
m
≥
K
num≥K
num≥K,那么此时一定是满足
P
×
K
>
s
u
m
P×K>sum
P×K>sum
2. 如果
n
u
m
=
K
−
1
num=K-1
num=K−1,那么为了保证不等式剩下的数的和一定
≥
P
≥P
≥P,又由于大小
<
P
<P
<P,所以个数一定
≥
2
≥2
≥2 且最大是
P
−
1
P-1
P−1,每次拿前
K
−
1
K-1
K−1大的数,剩下的一个数从小数中拿,由于剩下的数的和一定
≥
P
≥P
≥P,所以最后拿完
P
P
P次后,拿出来的数的和一定满足
P
×
K
>
s
u
m
P×K>sum
P×K>sum
3. 如果
n
u
m
=
K
−
2
num=K-2
num=K−2,那么为了保证不等式剩下的数的和一定
≥
P
≥P
≥P
又由于大小
<
P
<P
<P,所以个数一定
≥
3
≥3
≥3,且最大是
P
−
1
P-1
P−1,每次拿前
K
−
2
K-2
K−2大的数,剩下的一个数从小数中拿,第一次拿一定成功,拿完后,开始第二次拿,此时不等式就是
s
u
m
−
k
≥
P
∗
K
−
K
sum-k≥P*K-K
sum−k≥P∗K−K,如果第二次拿失败了,说明剩下的
3
3
3个数中,有至少2个数是
0
0
0,这就说明之前有两个数是
1
1
1,且这两个数是剩下的数中最大的两个,那么就说明剩下的三个数是最大情况就是 1,1,0,由于而这与中间推导的个数一定
>
=
3
>=3
>=3,所以第二次拿一定是可以的,…一直推导到可以拿
P
P
P次
…
K-1. 如果
n
u
m
=
0
num=0
num=0,…个数一定
≥
K
−
1
≥K-1
≥K−1,…按照上面归纳总结即可
最后按照不等式
P
×
K
≤
s
u
m
P×K≤sum
P×K≤sum,来二分即可
洛谷也有别的结论及证明 link.
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define ll long long
ll a[N];
int n, k;
bool check(ll x)
ll sum = 0;
ll cnt = 0;
for (int i = 1; i <= n; i++)
sum += min(x, a[i]);
return sum >= x * k;
int main()
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i];
ll l = 0, r = 1e18 / k;
while (l < r)
ll mid = (l + r + 1) / 2;
if (check(mid))
l = mid;
else
r = mid - 1;
cout << l << endl;
E - Swap
题意:
给定一个只有 K , E , Y K,E,Y K,E,Y字母的一个字符串,现在问最多能交换相邻字符串 K K K次,问能形成多少种字符串
思路:
原字符串定义为
A
A
A,变换后的字符串定义为
B
B
B
定义
d
p
(
i
,
e
,
y
,
x
)
dp(i,e,y,x)
dp(i,e,y,x)为
B
B
B字符串前
i
i
i位有
e
个
E
e个E
e个E
y
个
Y
y个Y
y个Y 需要操作
x
x
x次才能变成与
A
A
A字符串前
i
−
e
−
y
个
K
i-e-y个K
i−e−y个K
e
个
E
e个E
e个E
y
个
Y
y个Y
y个Y的相对顺序一致
最终就是
d
p
(
l
e
n
,
e
c
n
t
,
y
c
n
t
,
i
)
dp(len,ecnt,ycnt,i)
dp(len,ecnt,ycnt,i)从0到k的累加
那么此时已知
d
p
(
i
,
e
,
y
,
x
)
dp(i,e,y,x)
dp(i,e,y,x)的话,看对
d
p
(
i
+
1
)
dp(i+1)
dp(i+1)产生什么影响即可
在当前状态下,如果末尾来了一个 K K K,这是第 i − e − y i-e-y i−e−y个 K K K为了保证相对位置一样,就需要新来的 K K K与原序列的第 i − e − y i-e-y i−e−AtCoder Beginner Contest 234
AtCoder Beginner Contest 115 题解