概述
A. 检测点查询
题意
求
n
n
n个点中距离关键点最近的三个点。
若距离相同,则取编号小的。
3
≤
n
≤
200
,
0
≤
∣
x
∣
,
∣
y
∣
≤
200
3le nle 200,0le|x|,|y|le200
3≤n≤200,0≤∣x∣,∣y∣≤200
题解
分别记录最小值,次小值,第三小值即可。
时间复杂度
O
(
n
)
O(n)
O(n)
#include <bits/stdc++.h>
#define sqr(x) ((x) * (x))
using namespace std;
typedef pair<int, int> Pii;
int n;
struct Point { int x, y; } p, q;
Pii m1 = {INT32_MAX, 0}, m2 = m1, m3 = m1;
inline int dis2(Point a, Point b) { return sqr(a.x - b.x) + sqr(a.y - b.y); }
inline void Ins(Pii x) {
if (x < m1) m3 = m2, m2 = m1, m1 = x;
else if (x < m2) m3 = m2, m2 = x;
else if (x < m3) m3 = x;
}
int main() {
scanf("%d%d%d", &n, &q.x, &q.y);
for (int i = 1; i <= n; ++i)
scanf("%d%d", &p.x, &p.y), Ins({dis2(p, q), i});
printf("%dn%dn%d", m1.second, m2.second, m3.second);
return 0;
}
B. 风险人群筛查
题意
给定一个矩形左下角和右上角的坐标。
有
n
n
n个人,给定这
n
n
n个人在
1
∼
t
1sim t
1∼t时刻的坐标。
求有多少人某时刻在出现矩形内;求有多少人至少连续
k
k
k个时刻在矩形内(边界也算)。
1
≤
n
≤
20
,
1
≤
k
≤
t
≤
1
0
3
1le nle20,1le kle tle10^3
1≤n≤20,1≤k≤t≤103
题解
第一问直接判断;第二问判断每个人在矩形内的最长连续时间是否大于等于
k
k
k即可。
时间复杂度
O
(
n
t
)
O(nt)
O(nt)
#include <bits/stdc++.h>
using namespace std;
int n, k, t, Ans1, Ans2;
struct Point {
int x, y;
inline void init() { scanf("%d%d", &x, &y); }
inline bool operator<=(const Point b) { return x <= b.x && y <= b.y; }
} LD, RU, p;
int main() {
scanf("%d%d%d", &n, &k, &t);
LD.init(), RU.init();
while (n--) {
int flag = 0, maxL = 0, L = 0;
for (int i = 1; i <= t; ++i) {
p.init();
if (LD <= p && p <= RU)
flag = 1, ++L;
else
maxL = max(maxL, L), L = 0;
}
maxL = max(maxL, L);
Ans1 += flag, Ans2 += maxL >= k;
}
printf("%dn%d", Ans1, Ans2);
return 0;
}
C. 点亮数字人生
题意
给定一个包含
n
n
n个节点的逻辑电路,每个节点有一个算符(
N
O
T
,
X
O
R
,
A
N
D
,
O
R
,
N
A
N
D
,
N
O
R
rm NOT,XOR,AND,OR,NAND,NOR
NOT,XOR,AND,OR,NAND,NOR),共有
m
m
m个输入端,每个节点至多有
k
k
k个输入源。
S
S
S组询问,给定所有
m
m
m个输入源的输入值
0
/
1
0/1
0/1和
s
o
s_o
so个节点的编号
s
1
,
s
2
,
.
.
.
,
s
s
o
s_1,s_2,...,s_{s_o}
s1,s2,...,sso。
若逻辑电路存在环,则输出
L
O
O
P
rm LOOP
LOOP;否则对于每组询问,求出节点
s
1
,
s
2
,
.
.
.
,
s
s
o
s_1,s_2,...,s_{s_o}
s1,s2,...,sso的结果。
Q
Q
Q组数据。
Q
≤
5
,
n
≤
500
,
k
≤
5
,
m
≤
k
n
,
S
≤
1
0
4
Qle5,nle500,kle5,mle kn,Sle10^4
Q≤5,n≤500,k≤5,m≤kn,S≤104
样例一对应的逻辑电路:
题解
根据输入的关系建立出相应的有向图(所有的输入源也当成一个点),利用拓扑排序直接求解即可。
时间复杂度
O
(
Q
S
(
n
+
m
)
)
O(QS(n+m))
O(QS(n+m))
#include <bits/stdc++.h>
using namespace std;
const int N = 3000 + 5;
typedef int arr[N];
int n, m, S, Cnt, Loop;
arr in, deg, op, Ans, s_;
vector<int> G[N], input[N];
vector<int> I_[10005];
inline int f(vector<int> input, int op) {
int y = 0;
if (!op) return !input[0]; // NOT
else if (op == 1) { // XOR
for (auto x : input)
y ^= x;
return y;
} else if ((op | 1) == 3) { // AND,NAND
y = input[0];
for (int i = 1; i < (int)input.size(); ++i)
y &= input[i];
return op & 1 ? !y : y;
} else { // OR,NOR
for (auto x : input)
y |= x;
return op & 1 ? !y : y;
}
}
inline void Topsort() {
if (Loop == 1)
return;
queue<int> q;
for (int i = 1; i <= n; ++i)
deg[i] = in[i], input[i].clear();
for (int i = n + 1; i <= n + m; ++i)
q.push(i);
while (!q.empty()) {
int u = q.front();
q.pop();
for (auto v : G[u]) {
input[v].push_back(Ans[u]);
if (!(--deg[v]))
Ans[v] = f(input[v], op[v]), q.push(v);
}
}
if (Loop == -1) {
for (int i = 1; i <= n; ++i)
if (deg[i])
return (void)(Loop = 1, puts("LOOP"));
Loop = 0;
}
for (int i = 1; i <= Cnt; ++i)
printf("%d%c", Ans[s_[i]], " n"[i == Cnt]);
}
inline int GetOP(char *s) {
if (s[0] == 'O') return 4;
if (s[0] == 'X') return 1;
if (s[0] == 'A') return 2;
if (s[1] == 'A') return 3;
if (s[2] == 'T') return 0;
return 5;
}
inline void Solve() {
for (int i = 1; i <= n + m; ++i)
in[i] = 0, G[i].clear();
for (int i = 1; i <= n; ++i) {
char s[5];
int u;
scanf("%s%d", s, &in[i]);
op[i] = GetOP(s);
for (int j = 1; j <= in[i]; ++j) {
scanf("%s", s);
if (s[0] == 'O')
sscanf(s, "O%d", &u), G[u].push_back(i);
else
sscanf(s, "I%d", &u), G[n + u].push_back(i);
}
}
Loop = -1;
scanf("%d", &S);
for (int i = 1; i <= S; ++i) {
I_[i].resize(m);
for (int j = 0; j < m; ++j)
scanf("%d", &I_[i][j]);
}
for (int i = 1; i <= S; ++i) {
for (int j = n + 1; j <= n + m; ++j)
Ans[j] = I_[i][j - n - 1];
scanf("%d", &Cnt);
for (int j = 1; j <= Cnt; ++j)
scanf("%d", s_ + j);
Topsort();
}
}
int main() {
scanf("%*d");
while (~scanf("%d%d", &m, &n))
Solve();
return 0;
}
D. 星际旅行
题意
给定一个半径为
r
r
r的
n
n
n维球体和
m
m
m个
n
n
n维点。
求每个点到剩下
m
−
1
m-1
m−1个点的不穿过球体的最短距离之和。
2
≤
n
≤
100
,
2
≤
m
≤
2000
,
1
≤
r
≤
1
0
3
,
0
≤
∣
x
∣
,
∣
y
∣
≤
1
0
3
2le nle100,2le mle2000,1le rle10^3,0le |x|,|y|le10^3
2≤n≤100,2≤m≤2000,1≤r≤103,0≤∣x∣,∣y∣≤103
题解
考虑二维的情况
其中
θ
1
=
∠
O
A
C
=
arcsin
r
∣
A
O
∣
θ
2
=
∠
O
B
D
=
arcsin
r
∣
B
O
∣
θ
3
=
∠
A
O
B
=
arccos
∣
A
O
∣
2
+
∣
B
O
∣
2
−
∣
A
B
∣
2
2
∣
A
O
∣
∣
B
O
∣
θ
4
=
∠
C
O
D
=
θ
3
−
(
π
2
−
θ
1
)
−
(
π
2
−
θ
2
)
=
θ
1
+
θ
2
+
θ
3
−
π
begin{aligned} theta_1&=angle OAC=arcsinfrac{r}{|AO|}\ theta_2&=angle OBD=arcsinfrac{r}{|BO|}\ theta_3&=angle AOB=arccosfrac{|AO|^2+|BO|^2-|AB|^2}{2|AO||BO|}\ theta_4&=angle COD=theta_3-(frac{pi}2-theta_1)-(frac{pi}2-theta_2)=theta_1+theta_2+theta_3-pi end{aligned}
θ1θ2θ3θ4=∠OAC=arcsin∣AO∣r=∠OBD=arcsin∣BO∣r=∠AOB=arccos2∣AO∣∣BO∣∣AO∣2+∣BO∣2−∣AB∣2=∠COD=θ3−(2π−θ1)−(2π−θ2)=θ1+θ2+θ3−π
则
d
i
s
(
A
,
B
)
=
A
C
‾
+
C
D
⌢
+
B
D
‾
=
∣
A
O
∣
2
−
r
2
+
∣
B
O
∣
2
−
r
2
+
r
θ
4
dis(A,B)=overline{AC}+overset{largefrown}{CD}+overline{BD}=sqrt{|AO|^2-r^2}+sqrt{|BO|^2-r^2}+rtheta_4
dis(A,B)=AC+CD⌢+BD=∣AO∣2−r2+∣BO∣2−r2+rθ4.
当线段
A
B
AB
AB与圆不相交时,依照上式计算出来的
θ
4
<
0
theta_4<0
θ4<0,判断一下即可。
注意常数,时间复杂度
O
(
n
m
2
)
O(nm^2)
O(nm2)
#include <bits/stdc++.h>
using namespace std;
const int N = 100 + 5, M = 2e3 + 5;
const double Pi = acos(-1);
int n, m, r, r2;
double dis[M][M];
struct Point {
int a[N];
inline void init() {
for (int i = 1; i <= n; ++i)
scanf("%d", a + i);
}
} O, p[M];
#define sqr(x) ((x) * (x))
inline int Len(Point a, Point b) {
int L = 0;
for (int i = 1; i <= n; ++i)
L += sqr(a.a[i] - b.a[i]);
return L;
}
int main() {
scanf("%d%d%d", &n, &m, &r);
O.init();
r2 = r * r;
for (int i = 1; i <= m; ++i)
p[i].init();
for (int i = 1; i <= m; ++i)
for (int j = i + 1; j <= m; ++j) {
double AO2 = Len(p[i], O), BO2 = Len(p[j], O), AB2 = Len(p[i], p[j]),
t1 = asin(r / sqrt(AO2)), t2 = asin(r / sqrt(BO2)),
t3 = acos((AO2 + BO2 - AB2) / (2 * sqrt(AO2 * BO2))),
t4 = t1 + t2 + t3 - Pi;
if (t4 < 0)
dis[i][j] = dis[j][i] = sqrt(AB2);
else
dis[i][j] = dis[j][i] = sqrt(AO2 - r2) + sqrt(BO2 - r2) + r * t4;
}
for (int i = 1; i <= m; ++i)
printf("%.10lfn", accumulate(dis[i] + 1, dis[i] + m + 1, 0.0));
return 0;
}
E. 密信与计数
简要题意
给你一个解码本和一堆单词。
求长度为k的密文:不包含单词为子串,且解密后的明文是由单词组成的。这样的字符串有多少种。
题解
大佬的口糊题解:
解码本一页很简单
n页就多记一维状态就好了
考虑一页的情况
先把字典翻译回去
得到不超过38个的密文串
对字典建ac自动机
对于ac自动机上每个节点
我们dp
如果走到终止节点就不转移
最后
以上就是迅速啤酒为你收集整理的第二十次CCF计算机软件能力认证A. 检测点查询B. 风险人群筛查C. 点亮数字人生D. 星际旅行E. 密信与计数的全部内容,希望文章能够帮你解决第二十次CCF计算机软件能力认证A. 检测点查询B. 风险人群筛查C. 点亮数字人生D. 星际旅行E. 密信与计数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复