ABC187 A~D
A - Large Digits
题目大意
给定两个三位整数
A
A
A和
B
B
B,求它们数位和的最大值。
数位和:例如,
123
123
123的数位和是
1
+
2
+
3
=
6
1+2+3=6
1+2+3=6。
100
≤
A
,
B
≤
999
100 \le A,B \le 999
100≤A,B≤999
输入格式
A B A~~B A B
输出格式
一行,即 A A A和 B B B数位和的最大值。
样例
输入 | 输出 |
---|---|
123 234 | 9 |
593 953 | 17 |
100 999 | 27 |
分析
直接按题目照做即可。
代码
#include <cstdio>
#include <algorithm>
using namespace std;
int main(int argc, char** argv)
{
char a[10], b[10];
scanf("%s%s", a, b);
int as = 0, bs = 0;
for(int i=0; a[i]; i++)
as += a[i] - '0';
for(int i=0; b[i]; i++)
bs += b[i] - '0';
printf("%d\n", max(as, bs));
return 0;
}
B - Gentle Pairs
题目大意
有
N
N
N个点,每个点的坐标是
(
x
i
,
y
i
)
(x_i,y_i)
(xi,yi),
x
x
x坐标互不相同。
有多少对符合“
−
1
≤
斜率
≤
1
-1\le斜率\le1
−1≤斜率≤1”的点?
1
≤
N
≤
1
0
3
1\le N\le 10^3
1≤N≤103
∣
x
i
∣
,
∣
y
i
∣
≤
1
0
3
|x_i|,|y_i|\le 10^3
∣xi∣,∣yi∣≤103
x
i
≠
x
j
x_i \ne x_j
xi=xj (
i
<
j
i < j
i<j)
输入格式
N
N
N
x
1
y
1
x_1~y_1
x1 y1
⋮
\vdots
⋮
x
n
y
n
x_n~y_n
xn yn
输出格式
输出答案。
样例
样例输入1
3
0 0
1 2
2 1
样例输出1
2
有三个点 ( 0 , 0 ) (0,0) (0,0)、 ( 1 , 2 ) (1,2) (1,2)、 ( 2 , 1 ) (2,1) (2,1)。
- ( 0 , 0 ) (0,0) (0,0)到 ( 1 , 2 ) (1,2) (1,2),斜率为 2 2 2;
- ( 0 , 0 ) (0,0) (0,0)到 ( 2 , 1 ) (2,1) (2,1),斜率为 1 2 \frac12 21;
- ( 1 , 2 ) (1,2) (1,2)到 ( 2 , 1 ) (2,1) (2,1),斜率为 − 1 -1 −1。
有 2 2 2对符合条件的点。
样例输入2
1
-691 273
样例输出2
0
只有 1 1 1个点,无法组成对,输出 0 0 0。
样例输入3
10
-31 -35
8 -36
22 64
5 73
-14 8
18 -58
-41 -85
1 -88
-21 -85
-11 82
样例输出3
11
分析
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1)到
(
x
2
,
y
2
)
(x_2,y_2)
(x2,y2)的斜率是
y
1
−
y
2
x
1
−
x
2
\frac{y_1-y_2}{x1-x2}
x1−x2y1−y2。
推理过程:
−
1
≤
y
1
−
y
2
x
1
−
x
2
≤
1
-1 \le \frac{y_1-y_2}{x_1-x_2} \le 1
−1≤x1−x2y1−y2≤1
∣
y
1
−
y
2
x
1
−
x
2
∣
≤
1
|\frac{y_1-y_2}{x_1-x_2}| \le 1
∣x1−x2y1−y2∣≤1
∣
y
1
−
y
2
∣
∣
x
1
−
x
2
∣
≤
1
\frac{|y_1-y_2|}{|x_1-x_2|}\le 1
∣x1−x2∣∣y1−y2∣≤1
为了防止浮点数精度误差,我们继续:
∣
y
1
−
y
2
∣
≤
∣
x
1
−
x
2
∣
|y_1-y_2|\le|x1-x2|
∣y1−y2∣≤∣x1−x2∣
这时,就可以写代码了。
代码
枚举所有对点即可。
#include <cstdio>
#include <cmath>
#define maxn 1005
using namespace std;
int x[maxn], y[maxn];
inline bool slope_check(int x1, int y1, int x2, int y2)
{
int dx = abs(x1 - x2), dy = abs(y1 - y2);
return dy <= dx;
}
int main(int argc, char** argv)
{
int n, cnt = 0;
scanf("%d", &n);
for(int i=0; i<n; i++)
scanf("%d%d", x + i, y + i);
for(int i=0; i<n-1; i++)
for(int j=i+1; j<n; j++)
if(slope_check(x[i], y[i], x[j], y[j]))
cnt ++;
printf("%d\n", cnt);
return 0;
}
C - 1-SAT
题目大意
给你
N
N
N个字符串
S
1
,
S
2
,
.
.
.
,
S
N
S_1,S_2,...,S_N
S1,S2,...,SN。每个字符串都由小写字母组成,前面有至多
1
1
1个!
。
找到
S
1
,
S
2
,
.
.
.
,
S
N
S_1,S_2,...,S_N
S1,S2,...,SN中任意一个字符串,使
S
S
S中出现了“!
+这个字符串”(没有引号)。如果没有符合条件的字符串,输出satisfiable
。
1
≤
N
≤
1
0
5
1\le N\le 10^5
1≤N≤105
1
≤
∣
S
i
∣
≤
10
1\le |S_i|\le 10
1≤∣Si∣≤10
输入格式
N
N
N
S
1
S_1
S1
⋮
\vdots
⋮
S
N
S_N
SN
输出格式
如果有符合条件的字符串,输出任意一个;
否则,输出satisfiable
。
样例
样例输入1
6
a
!a
b
!c
d
!d
样例输出1
a
S
1
S_1
S1为a
,
S
2
S_2
S2为!a
,所以
S
1
S_1
S1符合条件;
S
5
S_5
S5为d
,
S
6
S_6
S6为!d
,所以
S
5
S_5
S5也符合条件,输出d
也会被判为正确。
样例输入2
10
red
red
red
!orange
yellow
!blue
cyan
!green
brown
!gray
样例输出2
satisfiable
没有符合条件的字符串。
分析
如果暴力去枚举两个字符串(如,a
和!a
),需要两重循环,复杂度为
O
(
N
2
)
\mathcal O(N^2)
O(N2)(由于字符串太短可以忽略字符串比较),这里
N
N
N最大为
1
0
5
10^5
105,所以,枚举法不可用。
我们再考虑
O
(
n
log
n
)
\mathcal O(n\log n)
O(nlogn)。
可以每次输入字符串时判断一下,如果它以!
开头将它的!
后面的内容放入set
中,否则将整个字符串放入vector
中。最后,循环遍历vector
(
O
(
n
)
\mathcal O(n)
O(n)),每次在set
中查找这个字符串(
O
(
log
n
)
\mathcal O(\log n)
O(logn))。总时间复杂度为
O
(
n
log
n
)
\mathcal O(n\log n)
O(nlogn)。
代码
#include <iostream>
#include <set>
#include <string>
#include <vector>
using namespace std;
vector<string> v;
set<string> s;
int main(int argc, char** argv)
{
ios::sync_with_stdio(false); cin.tie(0);
int n;
cin >> n;
while(n--)
{
string x;
cin >> x;
if(x[0] == '!')
s.insert(x.substr(1));
else v.push_back(x);
}
for(int i=0; i<v.size(); i++)
if(s.find(v[i]) != s.end())
{
cout << v[i] << endl;
return 0;
}
cout << "satisfiable\n";
return 0;
}
D - Choose Me
题目大意
略,请自行前往AtCoder查看。
数据范围:
1
≤
N
≤
1
0
5
1\le N\le 10^5
1≤N≤105
1
≤
A
i
,
B
i
≤
1
0
9
1\le A_i,B_i\le 10^9
1≤Ai,Bi≤109
输入格式
N
N
N
A
1
B
1
A_1~B_1
A1 B1
⋮
\vdots
⋮
A
N
B
N
A_N~B_N
AN BN
输出格式
输出答案。
样例
样例输入1
4
2 1
2 2
5 1
1 3
样例输出1
1
Takahashi
在第三个城市演讲后,Aoki
和Takahashi
将分别得到
5
5
5和
6
6
6个投票。
样例输入2
5
2 1
2 1
2 1
2 1
2 1
样例输出2
3
在任意三个城市演讲后,Aoki
和Takahashi
将分别得到
4
4
4和
9
9
9个投票。
样例输入3
1
273 691
样例输出3
1
分析
换句话说,我们的目的就是使得Aoki
和Takahashi
的票数差距逐渐减少。
最开始,票数的差距是Aoki
票数的和,也就是
∑
i
=
1
n
A
i
\sum\limits_{i=1}^nA_i
i=1∑nAi。
每去第
i
i
i个城市,差距减少
2
A
i
+
B
i
2A_i+B_i
2Ai+Bi,因此,我们可以贪心地先前往差距减少多的城市。这一点可以用数组+排序
、set
、priority_queue
三种方法实现(我选择的是priority_queue
,set
和priority_queue
更快一些)。
代码
注意:一定不能忘记使用long long!!!
#include <cstdio>
#include <queue>
using namespace std;
typedef long long LL;
priority_queue<LL> q;
int main(int argc, char** argv)
{
int n;
scanf("%d", &n);
LL diff = 0;
while(n--)
{
LL ao, ta;
scanf("%lld%lld", &ao, &ta);
diff += ao;
q.push(ao + ao + ta);
}
int ans = 0;
while(!q.empty())
{
ans ++;
if((diff -= q.top()) < 0)
{
printf("%d\n", ans);
return 0;
}
q.pop();
}
return 0;
}