ABC205 A~E
- [A - kcal](https://atcoder.jp/contests/abc205/tasks/abc205_a)
- [B - Permutation Check](https://atcoder.jp/contests/abc205/tasks/abc205_b)
- [C - POW](https://atcoder.jp/contests/abc205/tasks/abc205_c)
- [D - Kth Excluded](https://atcoder.jp/contests/abc205/tasks/abc205_d)
- [E - White and Black Balls](https://atcoder.jp/contests/abc205/tasks/abc205_e)
A - kcal
题目大意
我们有一种每 100 100 100毫升含有 A A A千卡热量的饮料。 B B B毫升的这种饮料含有多少千卡热量?
0 ≤ A , B ≤ 1000 0\le A, B\le 1000 0≤A,B≤1000
输入格式
A B A~B A B
输出格式
输出 B B B毫升这种饮料包含的的千卡数。最大允许浮点数精度误差 1 0 − 6 10^{-6} 10−6。
样例
A A A | B B B | 输出 |
---|---|---|
45 45 45 | 200 200 200 | 90 90 90 |
37 37 37 | 450 450 450 | 166.5 166.5 166.5 |
0 0 0 | 1000 1000 1000 | 0 0 0 |
50 50 50 | 0 0 0 | 0 0 0 |
分析
废话不多说,答案就是 A B 100 \frac{AB}{100} 100AB~
代码
#include <cstdio>
using namespace std;
int main()
{
int a, b;
scanf("%d%d", &a, &b);
a *= b;
printf("%d.%d\n", a / 100, a % 100);
return 0;
}
B - Permutation Check
题目大意
给定长度为
N
N
N的序列
A
=
(
A
1
,
A
2
,
…
,
A
N
)
A=(A_1,A_2,\dots,A_N)
A=(A1,A2,…,AN)。
判断
A
A
A是否为
(
1
,
2
,
…
,
N
)
(1,2,\dots,N)
(1,2,…,N)的一种排列。
1 ≤ A i ≤ N ≤ 1 0 3 1\le A_i\le N\le 10^3 1≤Ai≤N≤103
输入格式
N
N
N
A
1
A
2
…
A
N
A_1~A_2~\dots~A_N
A1 A2 … AN
输出格式
如果
A
A
A是
(
1
,
2
,
…
,
N
)
(1,2,\dots,N)
(1,2,…,N)的一种排列,输出Yes
;否则,输出No
。
样例
样例输入1
5
3 1 2 4 5
样例输出1
Yes
(
3
,
1
,
2
,
4
,
5
)
(3,1,2,4,5)
(3,1,2,4,5)是
(
1
,
2
,
3
,
4
,
5
)
(1,2,3,4,5)
(1,2,3,4,5)的一种排列,所以我们输出Yes
。
样例输入2
6
3 1 4 1 5 2
样例输出2
No
(
3
,
1
,
4
,
1
,
5
,
2
)
(3,1,4,1,5,2)
(3,1,4,1,5,2)不是
(
1
,
2
,
3
,
4
,
5
,
6
)
(1,2,3,4,5,6)
(1,2,3,4,5,6)的一种排列,所以我们输出No
。
样例输入3
3
1 2 3
样例输出3
Yes
样例输入4
1
1
样例输出4
Yes
分析
由于题目保证 1 ≤ A i ≤ N 1\le A_i\le N 1≤Ai≤N,所以 ( 1 , 2 , … , N ) (1,2,\dots,N) (1,2,…,N)的一种排列 A A A定义如下:
- A A A中 1 1 1到 N N N每个数字不重复出现。
因此,我们可以用数组记录每个数字是否出现,所以总时间复杂度为 O ( n ) \mathcal O(n) O(n)。
代码
#include <cstdio>
#define maxn 1005
using namespace std;
bool used[maxn];
int main()
{
int n;
scanf("%d", &n);
for(int i=0; i<n; i++)
{
int a;
scanf("%d", &a);
if(used[a])
{
puts("No");
return 0;
}
used[a] = true;
}
puts("Yes");
return 0;
}
C - POW
题目大意
给定三个整数 A , B , C A,B,C A,B,C,判断 A C A^C AC和 B C B^C BC哪个更大。
−
1
0
9
≤
A
,
B
≤
1
0
9
-10^9\le A,B\le 10^9
−109≤A,B≤109
1
≤
C
≤
1
0
9
1\le C\le 10^9
1≤C≤109
输入格式
A B C A~B~C A B C
输出格式
本题分如下三种情况输出:
- 如果
A
C
<
B
C
A^C<B^C
AC<BC,输出
<
; - 如果
A
C
>
B
C
A^C>B^C
AC>BC,输出
>
; - 如果
A
C
=
B
C
A^C=B^C
AC=BC,输出
=
。
样例
A A A | B B B | C C C | 输出 |
---|---|---|---|
3 3 3 | 2 2 2 | 4 4 4 | > |
− 7 -7 −7 | 7 7 7 | 2 2 2 | = |
− 8 -8 −8 | 6 6 6 | 3 3 3 | < |
分析
首先,由于负负得正,
(
−
a
)
2
=
a
2
(-a)^2=a^2
(−a)2=a2。
这样,我们可以根据奇偶性得出,如果
n
n
n为偶数,
(
−
a
)
n
=
a
n
(-a)^n=a^n
(−a)n=an;但如果
n
n
n为奇数,则
(
−
a
)
n
=
−
(
a
n
)
(-a)^n=-(a^n)
(−a)n=−(an)。
因此,我们只需判断如果
C
C
C为偶数,将
A
A
A替换为
∣
A
∣
|A|
∣A∣,再将
B
B
B替换为
∣
B
∣
|B|
∣B∣。
最后,
A
A
A和
B
B
B的大小关系就是
A
C
A^C
AC和
B
C
B^C
BC的大小关系。
代码
#include <cstdio>
using namespace std;
int main()
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if(!(c & 1))
{
if(a < 0) a = -a;
if(b < 0) b = -b;
}
puts(a < b? "<": a > b? ">": "=");
return 0;
}
D - Kth Excluded
题目大意
给定长度为
N
N
N的正整数序列
A
=
(
A
1
,
A
2
,
…
,
A
N
)
A=(A_1,A_2,\dots,A_N)
A=(A1,A2,…,AN)和
Q
Q
Q次查询。
在第
i
i
i次查询中,给定正整数
K
i
K_i
Ki,求第
K
i
K_i
Ki小的不在
A
A
A中的正整数。
1
≤
N
,
Q
≤
1
0
5
1\le N,Q\le 10^5
1≤N,Q≤105
1
≤
A
1
<
A
2
<
⋯
<
A
N
≤
1
0
18
1\le A_1<A_2<\dots<A_N\le10^{18}
1≤A1<A2<⋯<AN≤1018
1
≤
K
i
≤
1
0
18
1\le K_i\le 10^{18}
1≤Ki≤1018
输入格式
N
Q
N~Q
N Q
A
1
A
2
…
A
N
A_1~A_2~\dots~A_N
A1 A2 … AN
K
1
K_1
K1
K
2
K_2
K2
⋮
\hspace{5pt}\vdots
⋮
K
N
K_N
KN
输出格式
输出 Q Q Q行。第 i i i行应该包含第 K i K_i Ki小的不在 A A A中的正整数。
样例
样例输入1
4 3
3 5 6 7
2
5
3
样例输出1
2
9
4
不在 A A A中的正整数有 1 , 2 , 4 , 8 , 9 , 10 , 11 , … 1,2,4,8,9,10,11,\dots 1,2,4,8,9,10,11,…,其中有:
- 第 2 2 2小的 2 2 2;
- 第 5 5 5小的 9 9 9;
- 第 3 3 3小的 4 4 4。
因此,我们应该依次输出2
,9
,4
。
样例输入2
5 2
1 2 3 4 5
1
10
样例输出2
6
15
分析
本题我们可以先预处理出 A A A中每个元素比它小的元素的数量,再二分查找即可。
代码
#include <cstdio>
#include <algorithm>
#define maxn 100005
using namespace std;
using LL = long long;
LL a[maxn];
int main()
{
int n, q;
scanf("%d%d", &n, &q);
for(int i=0; i<n; i++)
{
scanf("%lld", a + i);
a[i] -= i;
}
while(q--)
{
LL k;
scanf("%lld", &k);
printf("%lld\n", k + (upper_bound(a, a + n, k) - a));
}
return 0;
}
E - White and Black Balls
题目大意
有多少种排列 N N N个白球和 M M M个黑球的方法使得下列条件成立?
- 对于每个 i i i ( 1 ≤ i ≤ N + M 1\le i\le N+M 1≤i≤N+M),设 w i w_i wi和 b i b_i bi分别是最左边 i i i个球中白球和黑球的数量, w i ≤ b i + K w_i\le b_i+K wi≤bi+K成立。
答案对 ( 1 0 9 + 7 ) (10^9+7) (109+7)取模。
0
≤
N
,
M
≤
1
0
6
0\le N,M\le10^6
0≤N,M≤106
1
≤
N
+
M
1\le N+M
1≤N+M
0
≤
K
≤
N
0\le K\le N
0≤K≤N
输入格式
N M K N~M~K N M K
输出格式
输出答案,对 ( 1 0 9 + 7 ) (10^9+7) (109+7)取模。
样例
N N N | M M M | K K K | 输出 |
---|---|---|---|
2 2 2 | 3 3 3 | 1 1 1 | 9 9 9 |
1 1 1 | 0 0 0 | 0 0 0 | 0 0 0 |
1000000 1000000 1000000 | 1000000 1000000 1000000 | 1000000 1000000 1000000 | 192151600 192151600 192151600 |
分析
首先,本题中合法排列数就是如下符合任意
y
≤
x
+
K
y\le x+K
y≤x+K的
(
0
,
0
)
→
(
M
,
N
)
(0,0)\to(M,N)
(0,0)→(M,N)的最短路径的数量:
由此可见,如果
N
>
M
+
K
N>M+K
N>M+K(即终点超出限制),答案一定为
0
0
0。
我们还可以发现,如果没有
y
≤
x
+
K
y\le x+K
y≤x+K这个限制,答案为
(
N
+
M
N
)
\binom{N + M}{N}
(NN+M)。
我们再考虑不合法的路径数,数量为
(
N
+
M
M
+
K
+
1
)
\binom{N + M}{M + K + 1}
(M+K+1N+M)。
因此,答案为
(
N
+
M
N
)
−
(
N
+
M
M
+
K
+
1
)
\binom{N + M}{N}-\binom{N + M}{M + K + 1}
(NN+M)−(M+K+1N+M)。
代码
这里用AtCoder Library
好像比较方便唉~
#include <iostream>
#include <atcoder/modint>
using namespace std;
using modint = atcoder::modint1000000007;
modint f(int n, int m)
{
if(n < 0 || m < 0)
return 0;
modint ret = 1;
for(int i=1; i<=m; i++)
ret = ret * (n + i) / i;
return ret;
}
int main()
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
if(n > m + k) puts("0");
else printf("%d\n", (f(n, m) - f(n - k - 1, m + k + 1)).val());
return 0;
}