玩转Django2.0---Django笔记建站基础九(二)(Auth认证系统)
9.4 设置用户权限
用户权限主要是对不同的用户设置不同的功能使用权限,而每个功能主要以模型来划分。以9.3节的MyDjango项目为例,在Admin后台管理系统可以查看并设置用户权限,如下图:
用户权限设置
上图左边列表框中列出了整个项目的用户权限,以user|用户|Can add user为例:
1、user代表项目的App。
2、用户代表App所定义的模型MyUser。
3、Can add user代表该权限可对模型MyUser执行新增操作。
一般情况下,在执行数据迁移时,每个模型默认拥有增(add), 改(change),删(delete)权限。数据迁移完成后,可以在数据库中查看数据表auth_permission的数据信息,每条数据信息代表项目中某个模型的某个权限,如下图:
设置用户权限实质上是对数据表user_myuser和auth_permission之间的数据设置多对多关系。首先需要了解用户、用户权限和用户组三者之间的关系,以MyDjango的数据表为例,如下图:
从整个项目的数据表可以看到,用户、用户权限和用户组分别对应数据表user_myuser、auth_permission和auth_group。无论是设置用户权限、设置用户所属用户组还是设置用户组的权限,其实质都是对两个数据表之间的数据建立多对多的数据关系,说明如下:
1、数据表user_myuser_user_permissions:管理数据表user_myuser和auth_permission之间的多对多关系,实现用户权限设置。
2、数据表user_myuser_groups:管理数据表user_myuser和auth_group之间的多对多关系,实现在用户组设置用户。
3、数据表auth_group_permissions:管理数据表auth_group和auth_permission之间的多对多关系,实现用户组设置权限。
实现用户的权限设置需要注意:如贵哦用户角色是超级用户,该用户是无须设置权限的,用户权限只适用于非超级用户。我们在PyCharm的Terminal下开启Django的shell模式来实现用户权限设置,代码如下:
(py3_3) E:\test5\MyDjango>python manage.py shell #导入模型MyUser
In [1]: from user.models import MyUser
#查询用户信息,filter查询返回列表格式,因此设置列表索引获取User对象
In [3]: user = MyUser.objects.filter(username='user1')[0]
#判断当前用户是否具有权限add_product
#index.add_product为固定写法,index为项目的App名,add_product是数据表auth_permission的字段codename
In [4]: user.has_perm('index.add_product')
Out[4]: False #导入模型Permission
In [5]: from django.contrib.auth.models import Permission #在权限管理表获取权限add_product的数据对象permission
In [7]: permission = Permission.objects.filter(codename='add_product')[0] #对当前用户对象user设置权限add_product
In [10]: user.user_permissions.add(permission) #再次判断当前用户是否具有权限add_product
In [12]: user.has_perm('index.add_product')
Out[12]: True
上述代码对用户名为user1的用户设置了产品信息的新增权限,打开数据表user_myuser_user_permissions可以看到新增了一条数据,如下图:
数据表user_myuser_user_permissions
数据表的字段myuser_id和permission_id分别是数据表user_myuser和auth_permission的主键,如上图上的每一条数据代表某个用户具有某个模型的某个操作权限。除了添加权限之外,还可以对用户的权限进行删除和查询,代码如下:
In [6]: user = MyUser.objects.filter(username='user1')[0] In [10]: permission = Permission.objects.filter(codename='add_product')[0] #删除某条权限
In [11]: user.user_permissions.remove(permission)
#判断是否已删除权限,若为False,说明删除成功。函数has_perm用于判断用户是否拥有权限
In [12]: user.has_perm('index.add_product')
Out[12]: False #清空当前用户全部权限
In [13]: user.user_permissions.clear() #获取当前用户所拥有的权限信息
#将上述删除的权限添加到数据表再查询
In [14]: user.user_permissions.add(permission) In [15]: user.user_permissions.values()
Out[15]: <QuerySet [{'id': 25, 'name': 'Can add product', 'content_type_id': 7, 'codename': 'add_product'}]>
9.5 自定义用户权限
一般情况下,每个模型默认拥有增(add),改(change),删(delete)权限。但实际开发中,可能要对某个模型设置特殊的权限,比如设置访问权限。为了解决这种情况,在定义模型的时候,可以在模型的Meta中设置自定义权限。以MyDjango为例,对index的模型Product重新定义,代码如下:
#index/models.py
class Product(models.Model):
id = models.AutoField('序号', primary_key=True)
name = models.CharField('名称',max_length=50)
weight = models.CharField('重量',max_length=20)
size = models.CharField('尺寸',max_length=20)
type = models.ForeignKey(Type, on_delete=models.CASCADE,verbose_name='产品类型')
# 设置返回值
def __str__(self):
return self.name class Meta:
#自定义权限
permissions = (
('visit_Product', 'Can visit Product'),
)
定义模型Product的时候,通过重写父类models.Model的permissions属性可实现自定义用户权限。该属性以元组或列表的数据格式表示,每个元素代表一个权限,也是以元组或列表表示。在一个权限中含有两个元素,如('add_Product', 'Can create Product'),add_product和Can create Product分别是数据表auth_permission的codename和name字段。
在数据库中清除MyDjango原有的数据表,并在PyCharm的Terminal中重新执行数据迁移,指令代码如下:
(py3_3) E:\test5\MyDjango>python manage.py makemigrations (py3_3) E:\test5\MyDjango>python manage.py migrate
指令执行完成后,在数据库中打开数据表auth_permission,可以找到自定义权限visit_Product,如下图:
自定义全visit_Product截图
9.6 设置网页的访问权限
本节中,结合实际的例子讲述如何在实际开发中使用用户权限,以MyDjango为例,数据表auth_permission已自定义权限visit_Product,数据表user_myuser分别创建了一名超级用户和一名普通用户,如下图:
数据表user_myuser的用户信息
本例需要将项目的index和user结合使用。index主要将权限应用到开发中,而user主要用于用户的注册、登录和退出登录,用于检验index的应用效果。
首先讲解user的开发流程,我们分别对路由urls.py、视图views.py和模板user.html进行相应开发,共同完成用户的注册、登录和退出登录,代码如下:
#路由user/urls.py
from django.urls import path
from . import views urlpatterns = [
#用户登录
path('login.html', views.loginView, name='login'),
#用户注册
path('register.html', views.registerView, name='register'), #退出登录
path('logout.html', views.logoutView, name='logout'),
] #视图user/views.py
from django.shortcuts import render, redirect
from .models import MyUser
from django.contrib.auth.models import Permission
from django.contrib.auth import login, authenticate, logout # 用户登录
def loginView(request):
tips = '请登录'
title = '用户登录'
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
if MyUser.objects.filter(username=username):
user = authenticate(username=username, password=password)
if user:
if user.is_active:
# 登录当前用户
login(request, user)
return redirect('/')
else:
tips = '账号密码错误,请重新输入'
else:
tips = '用户不存在,请注册'
return render(request, 'user.html', locals()) # 用户注册
def registerView(request):
title = '用户注册'
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
if MyUser.objects.filter(username=username):
tips = '用户已存在'
else:
user = MyUser.objects.create_user(username=username, password=password)
user.save()
# 添加权限
permission = Permission.objects.filter(codename='visit_Product')[0]
user.user_permissions.add(permission)
return redirect('/user/login.html')
return render(request, 'user.html', locals()) # 退出登录
def logoutView(request):
logout(request)
return redirect('/')
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
<link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css">
</head>
<body>
<div class="flex-center">
<div class="container">
<div class="flex-center">
<div class="unit-1-2 unit-1-on-mobile">
<h1>MyDjango Auth</h1>
{% if tips %}
<div>{{ tips }}</div>
{% endif %}
<form class="form" action="" method="post">
{% csrf_token %}
<div>用户名:<input type="text" name='username'></div>
<div>密 码:<input type="password" name='password'></div>
<button type="submit" class="btn btn-primary btn-block">确定</button>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
上述代码主要实现一个简单的操作流程,流程顺序为用户注册->用户登录->访问首页,具体实现过程如下:
1、首先用户访问用户注册界面,输入新的用户信息并单击"确定"按钮,提交用户注册信息到网站后台。
2、后台的视图函数registerView接收表单数据,判断当前注册的用户是否存在。如果用户不存在,将表单数据保存到数据表user_myuser中,创建新的用户信息。
3、默认情况下,新创建的用户是没有设置任何权限的,视图函数对新创建的用户设置visit_Product权限。注册成功后,程序会自动跳转到用户登录界面。
4、在用户登录界面输入新创建的用户信息,完成用户登录后,程序会自动跳转到网站的首页。
在user中实现了用户的权限设置,为新创建的用户添加visit_Product权限,接着在index中实现用户权限的校验。在index的路由urls.py、视图views.py和模板index.html中分别编写以下代码:
#index/urls.py
from django.urls import path
from . import views
urlpatterns = [
# 首页的URL
path('', views.index),
] #index/views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required, permission_required # 使用login_required和permission_required分别对用户登录验证和用户权限验证
@login_required(login_url='/user/login.html')
@permission_required(perm='index.visit_Product', login_url='/user/login.html')
def index(request):
return render(request, 'index.html', locals())
在视图函数index中使用了装饰器login_required和permission_required,分别对当前用户的登录状态和用户权限进行校验,说明如下:
login_required:设置用户登录访问权限。如果当前用户尚未在用户登录界面完成登录而直接访问首页,程序自动跳转到登录界面,只有用户完成登录后才能访问首页。login_required的参数有redirect_field_name和login_url。
1、参数redirect_field_name:默认值是next。当登录成功之后,程序会自动跳回之前浏览的网页。
2、参数login_url:设置登录界面的URL地址。默认值是settings.py的属性LOGIN_URL,而属性LOGIN_URL需要开发者自行在settings.py中配置。
permission_required:验证当前用户是否拥有相应的权限。若用户没有使用权限,程序会跳转到登录界面或者抛出异常。permission_required的参数如下。
1、参数perm:必须参数,判断当前用户是否拥有权限。参数值为固定格式,如index.visit_Product,index为项目的App名,visit_product来自数据表auth_permission的字段codename。
2、参数login_url:设置登录界面的URL地址,默认值为None。若不设置参数,验证失败后会抛出404异常。
3、参数raise_exception:设置抛出异常,默认值为False。
装饰器permission_required的作用与内置函数has_perm相同,上述代码也可以使用函数has_perm实现装饰器permission_required的功能,代码如下:
#使用函数has_perm实现装饰器permission_required功能
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required @login_required(login_url='/user/login.html')
def index(request):
user = request.user
if user.has_perm('index.visit_Product'): return render(request, 'index.html', locals())
else:
return redirect('/user/login.html')
最后在模板index.html中实现用户权限判断,这也是权限校验的使用方法之一。模板index.html的<header>标签代码修改如下:
<header id="top">
<!-- 内容显示区域 :width : 1211px -->
<div id="top_box">
<ul class="lf">
<li><a href="#">华为官网</a></li>
<li><a href="#">华为荣耀</a></li>
</ul>
<ul class="rt">
{#在模版中使用user变量是一个User或者AnoymousUser对象,该对象由模型MyUser实例化#}
{% if user.is_authenticated %}
<li>用户名: {{ user.username }}</li>
<li><a href="{% url 'logout' %}">退出登录</a></li>
{% endif %}
{#在模版中使用perms变量是Permission对象,该对象由模型Permission实例化#}
{% if perms.index.add_product %}
<li>添加产品信息</li>
{% endif %}
</ul>
</div>
</header>
在模板index.html中分别使用变量user和perms,但从视图函数index总可以发现,视图函数并没有将变量user和perms传递给模板。其实变量user和perms是由Django自动生成的,变量的生成与配置五年级settings.py的TEMPLATES设置有关,我们查看setting.py的TEMPLATES配置信息,代码如下:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'index/templates'),
os.path.join(BASE_DIR, 'user/templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
因为TEMPLATES中定义了处理器集合context_processors,所以在解析模板Template之前,Django首先依次运行处理器集合的程序。当运行到处理器django.contrib.auth.context_processors.auth时,程序会生成变量user和perms,并且将变量传入模板变量TemplateContext中,所以在模板中可以直接使用变量user和perms。
从上述例子可以看到,项目的user主要实现权限的设置功能;项目的index主要实现权限的使用,权限的使用主要判断当前用户是否具有权限的使用资格,而权限的判断可以从视图函数或模板语法实现。在浏览器上分别使用超级用户和普通用户登录网站,两者的首页信息如下图:
9.7 设置用户组
顾明思义,用户组就是对用户进行分组管理,其作用是在权限控制中可以批量地对用户的权限进行分配,而不同一个一个地按用户组所分配的所有权限。例如用户组teachers拥有权限can_create_lesson,那么所有属于teachers的用户都会有can_create_lesson权限。
我们知道用户、权限和用户组三者之间是多对多的数据关系,而用户组可以理解为用户和权限之间的中转站。设置用户组分为两个步骤:设置用户组的权限和设置用户组的用户。
设置用户组的权限主要对数据表auth_group和auth_permission构建多对多的数据关系,数据关系保存在数据表auth_group_permissions中。以MyDjango为例,其数据库结构如下图所示:
数据库结构
在数据表auth_group中创建三条数据信息:产品信息、产品类型和用户管理,每条信息在项目中代表一个用户组,如下图:
数据表auth_group
我们在PyCharm的Terminal中使用Django的shell模式来实现用户组的权限配置,代码如下:
#用户组的权限配置
#导入内置模型Group和Permission
(py3_3) E:\test5\MyDjango>python manage.py shell In [1]: from django.contrib.auth.models import Group In [2]: from django.contrib.auth.models import Permission #获取某个权限对象permission
In [3]: permission = Permission.objects.get(codename='visit_Product') #获取某个用户组对象group
In [4]: group = Group.objects.get(id=1) #将权限permission添加到用户组group中
In [5]: group.permissions.add(permission)
上述代码将visit_Product权限添加到用户组(产品信息),功能实现过程如下:
1、从数据表auth_group获取用户组(产品信息)对象group,对象group代表数据表总某一条数据。
2、从数据表auth_permission获取权限(visit_Product)对象permission,对象permission代表数据表中某一条数据。
3、使用permissions.add方法将权限对象permission与用户组对象group构建多对多数据关系并保存在数据表auth_group_permissions中。查看数据表auth_group_permissions,数据信息如下图:
数据表auth_group_permissions
除了添加用户组的权限之外,还可以删除用户组已有的权限,代码如下:
#删除当前用户组group的visit_Product权限
In [6]: group.permissions.remove(permission)
#删除当前用户组group的全部权限
In [7]: group.permissions.clear()
设置用户组的用户主要对数据表auth_group和user_myuser构建多对多数据关系,数据关系保存在数据表user_myuser_groups中。在Django的shell模式下实现用户组的用户设置,代码如下:
#将用户分配到用户组
#导入模型Group和MyUser
In [8]: from user.models import MyUser In [9]: from django.contrib.auth.models import Group #获取用户对象user,对象user代表用户名为user1的数据信息
In [11]: user = MyUser.objects.get(username='user1') #获取用户组对象group,对象group代表用户组(产品信息)的数据信息
In [13]: group = Group.objects.get(id=1) #将用户添加到用户组
In [14]: user.groups.add(group)
上述代码将用户名为user1的用户添加到用户组(产品信息),功能实现过程与用户组的权限设置是相似的,只不过两者所使用的模型有所不同。查看数据表user_myuser_groups,数据信息如下图:
数据表user_myuser_groups
除了添加用户组的用户之外,还可以删除用户组已有的用户,代码如下:
#删除用户组某一用户
In [15]: user.groups.remove(group)
#情况用户组全部用户
In [16]: user.groups.clear()
9.8 本章小结
Django除了有强大的Admin管理系统之外,还提供了完善的用户管理系统。整个用户管理系统可分为三大部分:用户信息、用户权限和用户组,在数据库中分别对应数据表auth_user、auth_permission和auth_group。
使用内置模型User和内置的函数可以快速实现用户管理功能,如用户注册、登录、密码修改、密码找回和用户注销。模型User的字段说明以及常用的内置函数如下。
模型User字段及说明
字段 | 说明 |
ID | int类型,数据表主键 |
Password | varchar类型,代表用户密码,在默认情况下使用pbkdf2_sha256方式来存储和管理用户的密码 |
last_login | datetime类型,最近一次登录的时间 |
is_superuser | tinyint类型,表示该用户是否拥有所有的权限,即是否为超级用户 |
Username | varchar类型,代表用户账号 |
first_name | varchar类型,代表用户的名字 |
last_name | varchar类型,代表用户的姓氏 |
varchar类型,代表用户的邮件 | |
is_staff | 用来判断用户是否可以登录进入Admin系统 |
is_active | tinyint类型,用来判断该账户的状态是否被激活 |
date_joined | datetime类型,账号的创建时间 |
常用的内置函数及说明
内置函数 | 说明 |
authenticate | 验证用户是否存在,必选参数为username和password,只能用于模型User |
create_user | 创建新的用户信息,必选参数为username,只能用于模型User |
set_password | 修改用户密码,必选参数为password,只能用于模型User |
login/logout | 用户的登录和注销,只能哟农户模型User |
make_password | 密码加密处理,必选参数为password,可脱离模型User单独使用 |
check_password | 检验加密前后的密码是否相同,可脱离模型User单独使用 |
email_user | 发送邮件,只能用于模型User |
send_mail | 发送邮件 |
send_mass_mail | 批量发送邮件 |
EmailMultiAlternatives | 发送自定义内容格式的邮件 |
Django提供了4中模型扩展的方法:
1、代理模型:这是一种模型继承,这种模型在数据库中无须创建新数据表。一般用于改变现有模型的行为方式,如增加新方法函数等,并且不影响现有数据库的结构。当不需要在数据库中存储额外的信息,而需要增加操作方法或更改模型的查询管理方式时,适合使用代理模型来扩展现有User模型。
2、Profile扩展模型User:当存储的信息与模型User相关,而且并不改变模型User原有的认证方法时,可定义新的模型MyUser,并设置某个字段为OneToOneField,这样能与模型User形成一对一关联,该方法称为用户配置(User Profile)。
3、AbstractBaseUser扩展模型User:当模型User的内置方法并不符合开发需求时,可使用该方法对模型User重新自定义设计,该方法对模型User和数据库架构影响很大。
4、AbstractUser扩展模型User:如果模型User的内置的方法符合开发需求,在不改变这些函数方法的情况下,添加模型User的额外字段,可通过AbstractUser方式实现。使用AbstractUser定义的模型会替换原有模型User。
用户、用户权限和用户组分别对应数据表user_myuser、auth_permission和auth_group。无论是设置用户权限、设置用户所属用户组还是设置用户组的权限,其实质都是对两个数据表之间的数据建立多对多的数据关系,说明如下:
1、数据表user_myuser_user_permissions:管理数据表user_myuser和auth_permission之间的多对多关系,实现用户权限设置。
2、数据表user_myuser_groups:管理数据表user_myuser和auth_group之间的多对多关系,实现在用户组设置用户。
3、数据表auth_group_permissions:管理数据表auth_group和auth_permission之间的多对多关系,实现用户组设置权限。
玩转Django2.0---Django笔记建站基础九(二)(Auth认证系统)的更多相关文章
- 玩转Django2.0---Django笔记建站基础九(一)(Auth认证系统)
第九章 Auth认证系统 Django除了有强大的Admin管理系统之外,还提供了完善的用户管理系统.整个用户管理系统可分为三大部分:用户信息.用户权限和用户组,在数据库中分别对应数据表auth_us ...
- 玩转Django2.0---Django笔记建站基础十一(二)((音乐网站开发))
11.5 歌曲排行榜 歌曲排行榜是通过首页的导航链接进入的,按照歌曲的播放次数进行降序显示.从排行榜页面的设计图可以看到,网页实现三个功能:网页顶部搜索.歌曲分类筛选和歌曲信息列表,其说明如下: 1. ...
- 玩转Django2.0---Django笔记建站基础十二(Django项目上线部署)
第十二章 Django项目上线部署 目前部署Django项目有两种主流方案:Nginx+uWsGI+Django或者Apache+uWSGI+Django.Nginx作为服务器最前端,负责接收浏览器的 ...
- 玩转Django2.0---Django笔记建站基础十(二)(常用的Web应用程序)
10.3 CSRF防护 CSRF(跨站请求伪造)也成为One Click Attack或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用,窃取网站的用户信息来制作 ...
- 玩转Django2.0---Django笔记建站基础十三(第三方功能应用)
第13章 第三方功能应用 在前面的章节中,我们主要讲述Django框架的内置功能以及使用方法,而本章主要讲述Django的第三方功能应用以及使用方法.通过本章的学习,读者能够在网站开发过程中快速开发网 ...
- 玩转Django2.0---Django笔记建站基础八(admin后台系统)
第八章 admin后台系统 admin后台系统也成为网站后台管理系统,主要用于对网站前台的信息进行管理,如文字.图片.影音和其他日常使用文件的发布.更新.删除等操作,也包括功能信息的统计和管理,如用户 ...
- django笔记 - 建站
1,建站步骤:1)django-admin.exe startproject mysite 创建完后的目录结构: - mysite # 对整个程序进行配置 - init - settings # 配置 ...
- 玩转Django2.0---Django笔记建站基础十(一)(常用的Web应用程序)
第十章 常用的Web应用程序 Django为开发者提供了常见的Web应用程序,如会话控制.高速缓存.CSRF防护.消息提示和分页功能.内置的Web应用程序大大优化了网站性能,并且完善了安全防护机制,而 ...
- 玩转Django2.0---Django笔记建站基础六(模型与数据库)
第六章 模型与数据库 Django对各种数据库提供了很好的支持,包括:PostgreSQL.MySQL.SQLite和Oracle,而且为这些数据库提供了统一的调用API,这些API统称为ORM框架. ...
随机推荐
- <数论相关>欧几里得与拓展欧几里得证明及应用
欧几里得算法 欧几里得算法的复杂度为O(log(n)),是一个非常高效的求最大公约数算法. 在这里不证明欧几里得算法的复杂度,有兴趣的可以访问以下链接:http://blog.sina.com.cn/ ...
- Docker应用容器引擎
1.Docker概述 1.1.Docker简介 Docker 是一个开源的应用容器引擎,基于 Go 语言开发.Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到 ...
- 牛客2018国庆集训 DAY1 D Love Live!(01字典树+启发式合并)
牛客2018国庆集训 DAY1 D Love Live!(01字典树+启发式合并) 题意:给你一颗树,要求找出简单路径上最大权值为1~n每个边权对应的最大异或和 题解: 根据异或的性质我们可以得到 \ ...
- presto,dremio,spark-sql与ranger的整合记录
dremio,spark-sql,presto和ranger的整合 当前,ranger没有现成的插件来管理dremio,spark-sql,presto. 暂时使用的方法是新建一个用户,如presto ...
- You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
异常 You are using the runtime-only build of Vue where the template compiler is not available. Either ...
- docker运行容器后agetty进程cpu占用率100%
1.最近在使用docker容器的时候,发现宿主机的agetty进程cpu占用率达到100% 在Google上搜了下,引起这个问题的原因是在使用"docker run"运行容器时使用 ...
- remote api
iperf -B 99.99.3.1 -c 192.168.42.242 -p 10002 -f m -i 1 -P 1 -w 1M -u -b 1M -t 20 iperf -B 192.168.4 ...
- 对“TD信息树”的使用体验
在本次同2017级学长进行的软件交流会上,我们有幸使用学长们开发的软件与成果,进过27个不尽相同的软件的使用,让我初步意识到了学习软件工程这门学科的实用价值.最终我选择了"TD信息树&quo ...
- 洛谷$P$3293 美味 $[SCOI2016]$ 主席树
正解:主席树 解题报告: 传送门! 挺有趣的,至少我不会$QAQ$(虽然我不会的多了去了$QAQ$ 如果没有这个所谓美味度限制可以直接线段树水过去嘛$QwQ$ 然后现在问的是个异或运算后的结果,关于异 ...
- $HDU1846\ Brave\ Game$ 博弈论
正解:博弈论 解题报告: 传送门! 巴什博奕板子题鸭$QwQ$ 就有个结论,是说当$(m+1)\mid n$时先手必败,否则必胜 这个瞎证明一下就能出来 就考虑当$(m+1)\mid 1$时,若先手取 ...