第二十次CCF计算机软件能力认证

数学专场

第一题:称检测点查询

解题思路:计算欧几里得距离
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

typedef pair<int , int> PII;
int n , x , y;
vector<PII>v;

int main()
{
    cin >> n >> x >> y;
    
    for(int i = 1;i <= n;i ++)
    {
        int a , b;
        cin >> a >> b;
        v.push_back({(a - x) * (a - x) + (b - y) * (b - y) , i});
    }
    sort(v.begin() , v.end());
    for(int i = 0;i < 3;i ++)
        cout << v[i].second << endl;
    
    return 0;
}

第二题:风险人群筛查

解题思路:

对于每一个记录一定是连续的,因此查询逗留的就是检查每一条数据有几个连续的点在矩阵中即可

对于每一个点使用线性规划直接检查是否在矩阵中即可

#include<iostream>

using namespace std;

const int N = 1010;
int n , k , t , xl , yl , xr , yr;
int x[N] , y[N];
int throu = 0 , stay = 0;

bool in(int u)
{
    if(x[u] >= xl && x[u] <= xr && y[u] >= yl && y[u] <= yr) return true;
    return false;
}

bool check() // 检查是否经过
{
    for(int i = 0;i < t;i ++)
        if(in(i)) return true;
    
    return false;
}

bool check1() // 检查连续
{
    for(int i = 0;i < t;i ++)
    {
        int j = i;
        while(j < t && in(j)) j ++;
        if(j - i >= k) return true;
        i = j;
    }
    return false;
}

int main()
{
    cin >> n >> k >> t >> xl >> yl >> xr >> yr;
    while(n --)
    {
        for(int i = 0;i < t;i ++)
            cin >> x[i] >> y[i];
        
        if(check()) throu ++;
        if(check1()) stay ++;
    }
    cout << throu << endl << stay << endl;
    return 0;
}

第三题:点亮数字人生

解题思路:

直接模拟(真的阴间的模拟90分)

#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<iostream>
#include<unordered_map>
#include<algorithm>
#include<vector>
#include<cstring>
#include<sstream>
#include<queue>

using namespace std;

typedef unordered_map<int , int> MPII;
typedef vector<int> VI;
typedef pair<int , int> PII;
const int N = 5010 , M = 1e6 + 10;
int h[M] , ne[M] , e[M] , idx = 0;
MPII input;
int n , m , t , q;
unordered_map<int , vector<int>>input_num , query;
bool st[M];
int in[M] , copy_in[M];
int res[M];

struct Logic
{
    string logic;
    int cnt;
    VI w;
}nodes[M];


inline int change_input(int u)
{
    return 5000 + u;
}

inline void add(int a , int b)
{
    e[idx] = b , ne[idx] = h[a] , h[a] = idx ++;
}

inline bool check()
{
    queue<int>q;
    int cnt = 0;
    for(int i = 1;i <= n;i ++)
        if(!in[i]) q.push(i) , cnt ++;
    
   
    while(!q.empty())
    {
        int t = q.front();
        q.pop();
        
        for(int i = h[t];~i;i = ne[i])
        {
            int j = e[i];
            in[j] --;
            if(!in[j]) q.push(j) , cnt ++;
        }
    }
    return cnt == n;
}

inline void init()
{
    memset(h , -1 , sizeof h);
    memset(ne , 0 , sizeof ne);
    memset(e , 0 , sizeof e);
    memset(copy_in , 0 , sizeof copy_in);
    idx = 0;
    input.clear();
    memset(st , 0 , sizeof st);
    input_num.clear() , query.clear();
    memset(in , 0 , sizeof in);
    
    for(int i = 1;i <= n;i ++)
        nodes[i].logic = "" , nodes[i].cnt = 0 , nodes[i].w.clear();
}

inline int eval(int j)
{
    int ans = 0;
    int cnt = nodes[j].cnt;
    if(nodes[j].logic == "NOT") ans = nodes[j].w[0] ^ 1;
    else if(nodes[j].logic == "AND")
    {
        ans = 1;
        for(int i = 0;i < cnt;i ++)
            ans &= nodes[j].w[i];
    }
    else if(nodes[j].logic == "OR")
    {
        for(int i : nodes[j].w)
            ans |= i;
    }
    else if(nodes[j].logic == "XOR")
    {
        ans = nodes[j].w[0];
        for(int i = 1;i < cnt;i ++)
            ans ^= nodes[j].w[i];
    }
    else if(nodes[j].logic == "NAND")
    {
        ans = 1;
        for(int i : nodes[j].w)
            ans &= i;
        ans = ans ^ 1;
    }
    else
    {
        for(int i : nodes[j].w)
            ans |= i;
        ans = ans ^ 1;
    }
    return ans;
}

inline void cal(int u)
{
    queue<PII>q;
    int copy[M];
    memcpy(copy , copy_in , sizeof copy_in);
    
    for(int i = 1;i <= m;i ++) 
        q.push({input_num[u][i - 1] , change_input(i)});
    
    while(!q.empty())
    {
        auto t = q.front();
        q.pop();
        
        int x = t.first , y = t.second;
        for(int i = h[y];~i;i = ne[i])
        {
            int j = e[i];
            copy[j] --;
            nodes[j].w.push_back(x);
            if(!copy[j])
            {
                int ans = eval(j);
                res[j] = ans;
                q.push({ans , j});
            }
        }
    }
}

int main()
{
    scanf("%d" ,&t);
    while(t --)
    {
        init();
        scanf("%d %d" ,&m ,&n);
        getchar();
        for(int i = 1;i <= n;i ++)
        {
            char s[N];
            // getline(cin , s);
            fgets(s , 2000 , stdin);
            stringstream ss(s);
            string str;
            ss >> str;
            string logic = str;
            ss >> str;
            int cnt = stoi(str);
            nodes[i].logic = logic;
            nodes[i].cnt = cnt;
            while(ss >> str) 
            {
                if(str[0] == 'O') // 表示第 n 个器件的输出连接到此输入端
                {
                    int x = stoi(str.substr(1));
                    add(x , i);
                    in[i] ++;
                    copy_in[i] ++;
                }
                else // 表示第 m 个输入信号连接到此输入端
                {
                    int x = stoi(str.substr(1));
                    int y = change_input(x);
                    add(y , i);
                    copy_in[i] ++;
                    if(!input[y]) input[y] = x; // 将输入端进行重新编号
                }
            }
        }
        
        scanf("%d" ,&q);
        for(int i = 0;i < q;i ++)
            for(int j = 1;j <= m;j ++)
            {
                int x;
                scanf("%d" ,&x);
                input_num[i].push_back(x);
            }
        
        
        for(int i = 0;i < q;i ++)
        {
            int x;
            scanf("%d" ,&x);
            for(int j = 0;j < x;j ++)
            {
                int y;
                scanf("%d" ,&y);
                query[i].push_back(y);
            }
        }
        if(!check()) // 检查是否自环
        {
            puts("LOOP");
            continue;
        }
        
        
        for(int i = 0;i < q;i ++) 
        {
            memset(res , 0 , sizeof res);
            cal(i);
            
            for(int j = 1;j <= n;j ++)
                nodes[j].w.clear();
            for(int p : query[i])
                printf("%d " ,res[p]);
            puts("");
        }
    }
}

第四题:星际旅行

解题思路:

根据AB直线到圆心的距离和三角形的三边关系可以

两种情况:

(1)当两点A、B构成的直线不经过圆,最短距离 |AB| 的直线距离

(2)当两点A、B构成的直线经过圆,我们连接A点和圆心O点,B点和圆心O点,可以构成一个三角形,使用余弦定理可以得到AB边所对的角的弧度,然后可以求出所对应的弧长。

import math

def SLdist(x , y):
    w = len(x)
    ans = 0
    for i in range(w):
        ans += (x[i] - y[i]) ** 2
    return ans ** 0.5

n , m = map(int , input().split())
r = int(input())
black = list(map(int , input().split()))
l , d , tangent = [] , [] , []
for _ in range(m):
    temp = list(map(int , input().split()))
    l.append(temp)
    ans = 0
    for i in range(n):
        ans += (temp[i] - black[i]) ** 2
    # 点到圆心的距离
    d.append(ans ** 0.5)
    # 切线长
    tangent.append((ans - r * r) ** 0.5)

res = [0 for i in range(m + 10)]
for i in range(m):
    A = l[i]
    for j in range(i):
        B = l[j]
        a , b , c = d[i] , d[j] , SLdist(A , B)
        # 海伦公式
        p = (a + b + c) / 2
        h = ((p * (p - a) * (p - b) * (p - c)) ** 0.5)
        h = h * 2
        if h >= r * c or a * a + c * c <= b * b or b * b + c * c <= a * a:
            res[i] += c
            res[j] += c
            continue
        
        alpha1 = math.acos(r / a)
        alpha2 = math.acos(r / b)
        beta = math.acos((a * a + b * b - c * c) / (2 * a * b))
        alpha = beta - alpha1 - alpha2
        x = (a * a - r * r) ** 0.5 + (b * b - r * r) ** 0.5 + alpha * r
        res[i] += x
        res[j] += x
for i in range(m):
    print(f'{res[i]:.15f}')
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 110, M = 2010;

int n, m;
double R;
double o[N], p[M][N];
double d[M], rd[M];
double ans[M];

inline double sqr(double x)
{
    return x * x;
}

int main()
{
    scanf("%d%d%lf", &n, &m, &R);
    for (int i = 0; i < n; i ++ ) scanf("%lf", &o[i]);
    for (int i = 0; i < m; i ++ )
    {
        double s = 0;
        for (int j = 0; j < n; j ++ )
        {
            scanf("%lf", &p[i][j]);
            s += sqr(p[i][j] - o[j]);
        }
        d[i] = sqrt(s);
        rd[i] = sqrt(s - sqr(R));
    }

    for (int i = 0; i < m; i ++ )
        for (int j = 0; j < i; j ++ )
        {
            double s = 0;
            for (int k = 0; k < n; k ++ ) s += sqr(p[i][k] - p[j][k]);
            double c = sqrt(s), a = d[i], b = d[j];
            double p = (a + b + c) / 2;
            double area = sqrt(p * (p - a) * (p - b) * (p - c));
            double h = area * 2 / c;
            if (h >= R || sqr(b) >= sqr(a) + s || sqr(a) >= sqr(b) + s)
            {
                ans[i] += c, ans[j] += c;
                continue;
            }
            double angle1 = acos((sqr(a) + sqr(b) - s) / (2 * a * b));
            double angle2 = acos(R / a);
            double angle3 = acos(R / b);
            double t = (angle1 - angle2 - angle3) * R + rd[i] + rd[j];
            ans[i] += t, ans[j] += t;
        }
    for (int i = 0; i < m; i ++ )
        printf("%.12lf\n", ans[i]);
    return 0;
}

第五题:密信与计数


            int p = tr[t][i];
            if (!p) tr[t][i] = tr[ne[t]][i];
            else
            {
                ne[p] = tr[ne[t]][i];
                cnt[p] += cnt[ne[p]];
                q[ ++ tt] = p;
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < 26; i ++ )
        for (int j = 1; j <= n; j ++ )
        {
            string str;
            cin >> str;
            g[str[0] - 'a'][j] = {i, stoi(str.substr(1))};
        }
    string str;
    while (cin >> str)
    {
        insert(str);
        strs.push_back(str);
    }

    build();

    f[0][0][1] = 1;
    for (int i = 0; i <= m; i ++ )
    {
        int sum = 0;
        for (int j = 0; j <= idx; j ++ )
            for (int k = 1; k <= n; k ++ )
            {
                if (!f[i][j][k]) continue;
                sum = (sum + f[i][j][k]) % MOD;
                for (auto& s: strs)
                {
                    if (i + s.size() > m) continue;
                    bool flag = true;
                    int x = j, y = k;
                    for (auto c: s)
                    {
                        int u = c - 'a';
                        auto& t = g[u][y];
                        x = tr[x][t.row];
                        if (cnt[x])
                        {
                            flag = false;
                            break;
                        }
                        y = t.next;
                    }
                    if (flag)
                    {
                        auto& v = f[i + s.size()][x][y];
                        v = (v + f[i][j][k]) % MOD;
                    }
                }
            }
        if (i) printf("%d\n", sum);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值