CCF-CSP26<2022-06>-第1/2/3题

202206-1 归一化处理

题目:202206-1

题目分析:

给出了数学上归一化的数学公式,直接按照要求完成即可。

AC代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin >> n;
	double a[n];
	double sum = 0;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
		sum += a[i];
	}
	double average = sum / n;
	double dtotal = 0;
	for (int i = 0; i < n; i++)
	{
		dtotal += (a[i] - average) * (a[i] - average);
	}
	dtotal /= n;
	for (int i = 0; i < n; i++)
	{
		cout << (a[i] - average) / sqrt(dtotal) << endl;
	}
	return 0;
}

202206-2 寻宝!大冒险!

为什么我的第一想法是这个???

题目:202206-2

题目分析:

【再更新】

60分代码:

【再更新】

70分代码:

【再更新】

AC代码:

【再更新】

202206-3 角色授权

题目分析:

在学习了数据库之后,对于这道题会更加熟悉。实际上本题就是模拟了数据库对于用户权限的管理。

这道大模拟题主要就是概念很复杂,不容易快速上手理解。

总结如下:

  • 用户:主体
  • 用户组:用户组里包括很多用户,这些用户有相同的权限
  • 角色:指明了一个用户可以执行的操作
  • 角色关联:一个用户和一个或多个角色之间的关系,角色关联是一个映射<角色,用户/用户组>
  • 待授权行为:包括主体,操作,资源三个部分

判断一个用户能否执行某个操作的过程是:

  1. 检查所有的角色关联的授权对象清单,如果清单中包含该用户的名称,或者该清单中包含该用户所属的某一个用户组的名称,那么选取该角色关联所关联的角色;
  2. 对于所有被选取的角色,判断这些角色是否能对该资源执行该操作,如果所有角色都不能执行该操作,那么不能执行该操作;
  3. 允许执行该操作。

判断一个角色能否对某个资源执行某个操作的过程是:

  1. 检查该角色的操作清单,如果该角色的操作清单中不包含该操作,且该角色的操作清单中也不包含字符串 *,那么不能执行该操作;
  2. 检查该角色的资源种类清单,如果该角色的资源种类清单中不包含该资源的种类,且该角色的资源种类清单中也不包含字符串 *,那么不能执行该操作;
  3. 检查该角色的资源名称清单,如果该角色的资源名称清单中不包含该资源的名称,且该角色的资源名称清单不是空数组,那么不能执行该操作;
  4. 允许执行该操作。

实际上只要从头到尾执行一遍题目的过程并且不遗漏,就可以拿到大部分的分数。

【注意】一定要按照题目要求由用户->角色再判断是否满足操作、资源类型、资源名。不能直接将角色的权限分配向用户。即不要对于用户A,我知道他有角色BCD,就直接把BCD的操作、资源类型、资源名分别求并,存储在角色A下,这样看上去虽然会简单好多,似乎是优化了。但这样不等价于题目的赋值方式。

反例:

用户A被赋予角色BC

角色B:操作abc、资源类型x、资源名y

角色C:操作def、资源类型z、资源名w

现在询问用户A是否可以操作a,资源类型z,资源名y,这是不可以的。

70分代码:

这个就是从头到尾纯模拟题目的意思,包括存储的结构和执行的操作,都是完全按照题目来的。

具体来说:

前面是读入并存储题目信息。

然后对于每一个被查询的用户(外层循环),先遍历角色链接这个结构体,寻找是否有角色的u数组包含这个用户(这个是单层循环),或者g数组包含这个用户所属的用户组(角色链接一重循环,用户组数组一重循环,这里是两重循环)。现在得到所有包含这个用户的角色,把它们放在一个vector里。

最后遍历这个vector,查看这些角色的所有权限,看看有没有执行被询问的操作、资源种类、资源名的权限。

这个方法实现的瓶颈在于外层循环内的两重循环,最坏的情况下,外层循环q,内层循环m*ng,就需要q*m*ng,5000*500*400,这能达到10^9,这已经是超时了,一般10^8对应1s的数量级,这都需要10s了。因此这个方法只能拿70%数据点。

下面是代码(完全由本人完成):

// -*- coding:utf-8 -*-

// File    :   202206-3.cpp
// Time    :   2024/03/26
// Author  :   wolf

#include <iostream>
#include <vector>
const int N = 501;

using namespace std;

// 存储角色信息
struct character
{
    string name;
    int nv;
    vector<string> op;
    int no;
    vector<string> rtype;
    int nn;
    vector<string> rname;
};

// 存储角色与用户/用户组的链接
struct character_link
{
    string cname;
    struct character ch;
    vector<string> u;
    vector<string> g;
};

vector<character> c;
vector<character_link> c_link;

int main()
{
    // 关闭同步
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    // 即使关闭同步,该算法还是会超时,这是算法本身的局限
    int n, m, q;
    cin >> n >> m >> q;
    for (int i = 0; i < n; i++)
    {
        struct character ctemp;
        cin >> ctemp.name;
        cin >> ctemp.nv;
        for (int j = 0; j < ctemp.nv; j++)
        {
            string temp;
            cin >> temp;
            ctemp.op.push_back(temp);
        }
        cin >> ctemp.no;
        for (int j = 0; j < ctemp.no; j++)
        {
            string temp;
            cin >> temp;
            ctemp.rtype.push_back(temp);
        }
        cin >> ctemp.nn;
        for (int j = 0; j < ctemp.nn; j++)
        {
            string temp;
            cin >> temp;
            ctemp.rname.push_back(temp);
        }
        c.push_back(ctemp);
    }
    for (int i = 0; i < m; i++)
    {
        struct character_link cltemp;
        cin >> cltemp.cname;
        for (unsigned int j = 0; j < c.size(); j++)
        {
            if (cltemp.cname == c[j].name)
            {
                cltemp.ch = c[j];
            }
        }
        int ns;
        cin >> ns;
        for (int j = 0; j < ns; j++)
        {
            string ug, ugname;
            cin >> ug >> ugname;
            if (ug == "u")
            {
                cltemp.u.push_back(ugname);
            }
            else if (ug == "g")
            {
                cltemp.g.push_back(ugname);
            }
            else
            {
                cout << "error" << endl;
            }
        }
        c_link.push_back(cltemp);
    }
    for (int i = 0; i < q; i++)
    {
        string query_user;
        cin >> query_user;
        int ng;
        vector<string> query_ugroup;
        cin >> ng;
        for (int j = 0; j < ng; j++)
        {
            string uboxtemp;
            cin >> uboxtemp;
            query_ugroup.push_back(uboxtemp);
        }
        string query_op, query_rtype, query_rname;
        cin >> query_op >> query_rtype >> query_rname;

        // excute
        int ans = 0; // default ok
        vector<character> target_c;
        for (unsigned int j = 0; j < c_link.size(); j++)
        {
            for (unsigned int k = 0; k < c_link[j].u.size(); k++)
            {
                if (query_user == c_link[j].u[k])
                {
                    target_c.push_back(c_link[j].ch);
                }
            }
            for (unsigned int k = 0; k < c_link[j].g.size(); k++)
            {
                for (unsigned int t = 0; t < query_ugroup.size(); t++)
                {
                    if (query_ugroup[t] == c_link[j].g[k])
                    {
                        target_c.push_back(c_link[j].ch);
                    }
                }
            }
        }
        for (unsigned int j = 0; j < target_c.size(); j++)
        {
            character cnow = target_c[j];
            // cout << cnow.name << endl;
            int flag1 = false, flag2 = false, flag3 = false; // default no
            for (unsigned int k = 0; k < cnow.op.size(); k++)
            {
                // cout << query_op << " " << cnow.op[k] << endl;
                if (query_op == cnow.op[k] || cnow.op[k] == "*")
                {
                    flag1 = true;
                    break;
                }
            }
            if (flag1 == false)
                continue;
            for (unsigned int k = 0; k < cnow.rtype.size(); k++)
            {
                // cout << query_op << " " << cnow.op[k] << endl;
                if (query_rtype == cnow.rtype[k] || cnow.rtype[k] == "*")
                {
                    flag2 = true;
                    break;
                }
            }
            if (flag2 == false)
                continue;
            if (cnow.rname.size() == 0)
                flag3 = true;
            else
            {
                for (unsigned int k = 0; k < cnow.rname.size(); k++)
                {
                    if (query_rname == cnow.rname[k])
                    {
                        flag3 = true;
                        break;
                    }
                }
            }
            if (flag3 == false)
                continue;
            // success
            if (flag1 == true && flag2 == true && flag3 == true)
            {
                ans = 1;
                break;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

AC代码:

基于上述的分析,我们可以发现瓶颈在于从角色链接去回溯用户对应的角色。如果我能从一开始就知道每一个用户对应哪些角色,是不是就能节省很多时间呢?c++真有这么神奇的数据结构。

使用STL库中的<map>,我们做了一些小改动:

建立<角色名称 - 角色本体>映射,在找到角色名称之后,可以使用find()直接对应到角色本体。

使用多元map保存用户,用户组和角色之间的关联关系,同样在拿到用户之后,使用find()就可以找到角色,不需要从角色的视角去遍历,使用多元map是因为对于一个用户键,可能有多个角色与之相对应,即一个用户被赋予了多个角色。

这里能显著提升效率,是因为<algorithm>中的find(),使用树结构查找,时间复杂度是O(logn),显著大于从角色视角去for循环再验证用户/用户组在不在里面,这样是O(n)。

主要发现还是大量运用了STL库的“黑科技”。

【有参考】https://blog.csdn.net/Andy_Xie007/article/details/133800502

// -*- coding:utf-8 -*-

// File    :   202206-3.cpp
// Time    :   2024/03/26
// Author  :   wolf

#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <unordered_set>
#include <vector>
// 有参考https://blog.csdn.net/Andy_Xie007/article/details/133800502
const int N = 501;

using namespace std;
struct character
{
    string name;
    set<string> op;    // 操作
    set<string> rtype; // 资源种类
    set<string> rname; // 资源名称
    // 使用unordered_set会加快速度:2.984s -> 2.39s
    // unordered_set<string> op;    / 操作
    // unordered_set<string> rtype; // 资源种类
    // unordered_set<string> rname; // 资源名称
};

map<string, character> c; // 角色名称 - 角色本体映射
// 使用find进行检索O(n)时间复杂度,比数组快

// 判断cnow角色是否有对(query_op,query_rtype,query_rname)的访问权限
// 使用&传递地址而不是参复制,节省大量时间,否则超时
int check(const character &cnow, const string &query_op, const string &query_rtype, const string &query_rname)
{
    if (cnow.op.count(query_op) == 0 && cnow.op.count("*") == 0)
        return 0;
    if (cnow.rtype.count(query_rtype) == 0 && cnow.rtype.count("*") == 0)
        return 0;
    if (cnow.rname.count(query_rname) == 0 && !cnow.rname.empty())
        return 0;
    return 1;
}

int main()
{
    // 关闭同步
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    // 加了以上三句话,由90->100
    int n, m, q;
    cin >> n >> m >> q;
    for (int i = 0; i < n; i++)
    {
        struct character ctemp;
        string temp;
        int nv, no, nn;
        cin >> ctemp.name;
        cin >> nv;
        for (int j = 0; j < nv; j++)
        {
            cin >> temp;
            ctemp.op.insert(temp);
        }
        cin >> no;
        for (int j = 0; j < no; j++)
        {
            cin >> temp;
            ctemp.rtype.insert(temp);
        }
        cin >> nn;
        for (int j = 0; j < nn; j++)
        {
            cin >> temp;
            ctemp.rname.insert(temp);
        }
        c.insert(make_pair(ctemp.name, ctemp));
    }

    // 使用多元map保存用户,用户组和角色之间的关联关系,查找会很快
    multimap<string, string> relative_u; // user - character
    multimap<string, string> relative_g; // group - character

    for (int i = 0; i < m; i++)
    {
        string cname;
        cin >> cname;
        int ns;
        cin >> ns;
        for (int j = 0; j < ns; j++)
        {
            string ug, ugname;
            cin >> ug >> ugname;
            if (ug == "u")
            {
                relative_u.insert(make_pair(ugname, cname));
            }
            else if (ug == "g")
            {
                relative_g.insert(make_pair(ugname, cname));
            }
            else
            {
                cout << "error" << endl;
            }
        }
    }
    for (int i = 0; i < q; i++)
    {
        string query_user;
        cin >> query_user;
        int ng;
        cin >> ng;
        vector<string> query_ugroup;
        for (int j = 0; j < ng; j++)
        {
            string uboxtemp;
            cin >> uboxtemp;
            query_ugroup.push_back(uboxtemp);
        }

        string query_op, query_rtype, query_rname;
        cin >> query_op >> query_rtype >> query_rname;

        // excute
        int flag = 0;
        vector<character> target_c;

        // u
        pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range_u = relative_u.equal_range(query_user);
        // auto range_u = relative_u.equal_range(query_user);
        for (auto it = range_u.first; it != range_u.second; it++)
        {
            if (check(c.find(it->second)->second, query_op, query_rtype, query_rname))
            {
                flag = 1;
                break;
            }
        }
        if (flag == 1)
        {
            cout << 1 << endl;
            continue;
        }

        // g
        for (unsigned int j = 0; j < query_ugroup.size(); j++)
        {
            pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range_g = relative_g.equal_range(query_ugroup[j]);
            // auto range_g = relative_g.equal_range(query_ugroup[j]);
            for (auto it = range_g.first; it != range_g.second; it++)
            {
                if (check(c.find(it->second)->second, query_op, query_rtype, query_rname))
                {
                    flag = 1;
                    break;
                }
            }
            if (flag == 1)
            {
                break;
            }
        }
        if (flag == 1)
        {
            cout << 1 << endl;
            continue;
        }
        cout << 0 << endl;
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/506092.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开关恒流源简介

目录 工作原理 设计要点 应用场景 初步想法&#xff0c;为参加活动先占贴&#xff08;带家人出去玩没时间搞~~&#xff09;&#xff0c;后面优化 开关恒流源是一种基于开关电源技术的恒流输出电源设备。它采用开关管进行高速的开关动作&#xff0c;通过控制开关管的导通和截…

【跟小嘉学 Linux 系统架构与开发】一、学习环境的准备与Linux系统概述

系列文章目录 【跟小嘉学 Linux 系统架构与开发】一、学习环境的准备与Linux系统介绍 文章目录 系列文章目录[TOC](文章目录) 前言一、Linux 概述1.1、GNU 与自由软件1.2、Linux是什么1.3、Linux 特色1.4、Linux的优缺点1.4.1、Linux 优点1.4.2、Linux 缺点 二、虚拟机介绍2.1…

数据结构与算法 顺序栈的基本运算

一、实验内容 编写一个程序sqstack.cpp&#xff0c;实现顺序栈的各种基本运算&#xff0c;并在此基础上写一个程序exp6.cpp,实现以下功能 初始化栈s判断栈是否为空依次进栈元素a,b,c,d,e判断栈是否为空输出出栈序列判断栈是否为空释放栈 二、实验步骤 1、sqstack.cpp 2、ex…

6.5物联网RK3399项目开发实录-驱动开发之LCD显示屏使用(wulianjishu666)

90款行业常用传感器单片机程序及资料【stm32,stc89c52,arduino适用】 链接&#xff1a;https://pan.baidu.com/s/1M3u8lcznKuXfN8NRoLYtTA?pwdc53f LCD使用 简介 AIO-3399J开发板外置了两个LCD屏接口&#xff0c;一个是EDP&#xff0c;一个是LVDS&#xff0c;接口对应板…

go: go.mod file not found in current directory or any parent directory.如何解决?

这个错误表明你正在执行 go get 命令&#xff0c;但是当前目录或任何父目录中都找不到 go.mod 文件。这可能是因为你的项目还没有使用 Go Modules 进行管理。 要解决这个问题&#xff0c;有几种方法&#xff1a; go mod init <module-name> 其中 <module-name>…

CentOS系统下Docker的安装教程

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

oracle+110个常用函数

ASCII 返回与指定的字符对应的十进制数; SQL> select ascii(A) A,ascii(a) a,ascii(0) zero,ascii( ) space from dual; A A ZERO SPACE --------- --------- --------- --------- 65 97 48 32 2. CHR 给出整数,返回对应的字符; SQL> select chr(54740) zhao,chr(65) chr…

C语言-malloc(申请函数)free(释放函数)

malloc和free的语法格式 malloc 函数是 C 语言标准库中的一个重要函数&#xff0c;用于动态分配内存。其语法如下&#xff1a; void *malloc(size_t size);这里的 void * 表示返回的是一个 void 类型的指针&#xff0c;实际上这个指针指向的是一个 char 类型的内存块。size_t …

R语言决策树(1)

数据集heart_learning.csv与heart_test.csv是关于心脏病的数据集&#xff0c;heart_learning.csv是训练数据集&#xff0c;heart_test.csv是测试数据集。要求&#xff1a;target和target2为因变量&#xff0c;其他诸变量为自变量。用决策树模型对target和target2做预测&#xf…

机器学习—— PU-Learning算法

机器学习—— PU-Learning算法 本篇博客将介绍PU-Learning算法的基本概念、基本流程、基本方法&#xff0c;并简单探讨Two-step PU Learning算法和无偏PU Learning算法的具体流程。最后&#xff0c;将通过Python代码实现一个简单的PU-Learning示例&#xff0c;以便更好地理解这…

事务传播行为Propagation

目录 背景Propagation测试程序1测试程序2分析 背景 前段时间&#xff0c;某个项目在部署时&#xff0c;被公司的一个检测拦截了&#xff0c;提示报错如下&#xff1a; Your code exists Method or Class with Transactional annotation that not use Propagation.REQUIRED.有…

npm镜像源证书过期问题解决

title: npm镜像源证书过期 search: 2024-02-29 文章目录 Failed to check for updates 问题ERR_PNPM_NO_PKG_MANIFESTnpm缓存清除指令权限不足导致删除不了解决方案npm创建基础配资文件 Failed to check for updates 问题 错误描述如上 检查完 node,vue,npm 的版本后都没啥问…

使用hping3网络工具构造TCP/IP数据包和进行DDos攻击

1 概述 hping3是一个强大的命令行工具&#xff0c;用于生成、发送和解析TCP/IP协议的数据包。它是开源的网络安全工具&#xff0c;由Salvatore Sanfilippo开发&#xff0c;主要应用于网络审计、安全测试和故障排查等领域。hping3不仅可以作为普通的网络连通性检测工具&#xf…

壁纸小程序Vue3(首页布局)

1.创建一个公共目录common来存放css和images App.vue中引用 <style lang"scss"> /*每个页面公共css */ import common/style/common-style.scss; </style> 2.渲染轮播图 <template><view class"homeLayout"><vi…

苍穹外卖04 (新增内表的外键id获取,多表分页查询,多表批量删除,修改先查在改内表外键id用主表的,起售时包含了“停售”状态的外关联表)

1. 新增套餐 1 需求分析和设计 业务规则&#xff1a; 套餐名称唯一 套餐必须属于某个分类 套餐必须包含菜品 名称、分类、价格、图片为必填项 添加菜品窗口需要根据分类类型来展示菜品 新增的套餐默认为停售状态 2 代码实现 1 根据分类id查询菜品 DishControllerGetMa…

手机有线投屏到直播姬pc端教程

1 打开哔哩哔哩直播姬客户端并登录(按下图进行操作) 2 手机用usb数据线连接电脑(若跳出安装驱动的弹窗点击确定或允许),usb的连接方式为仅充电(手机差异要求为仅充电),不同品牌手机要求可能不一样,根据实际的来 3 在投屏过程中不要更改usb的连接方式(不然电脑会死机需要重启) …

SAP 学习笔记 - 系统移行业务 - Migration cockpit工具 - 移行Material(品目)

本章开始&#xff0c;来研究研究移行工具 Migration cockpit。 理论啥的先放一边&#xff0c;来先做一个简单的实例&#xff0c;以对 Migration cockpit 有个大概的印象。 这里就先做一个移行品目的例子。 1&#xff0c;LTMC 启动Migration cockpit工具 默认给我启动了 IE &a…

C++11入门手册第二节,学完直接上手Qt(共两节)

C++多线程 #include <thread>:C++多线程库 #include <mutex>:C++互斥量库 #include <future>:C++异步库 多线程介绍 线程的创建 void entry_1() { }以普通函数作为线程入口函数:void entry_2(int val) { }​std::thread my_thread_1(entry_1);std::thr…

【b站李炎恢】Vue.js Element UI 下 | 十天技能课堂 | 更新中... | 李炎恢

课程地址&#xff1a;【Vue.js Element UI | 十天技能课堂 | 更新中... | 李炎恢】 https://www.bilibili.com/video/BV1U54y127GB/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 备注&#xff1a;虽然标题声明还在更新中&#xff0c;但是看一些常用…

npm软件包管理器

npm软件包管理器 一.npm 使用步骤二.npm安装所有依赖三.npm全局软件包-nodemon pm 简介链接&#xff1a; 软件包管理器&#xff0c;用于下载和管理 Node.js 环境中的软件包 一.npm 使用步骤 1.初始化清单文件&#xff1a; npm init -y &#xff08;得到 package.json 文件&am…