【前言】OJ:CCF-CSP 模拟考试
1 201612-1 中间数
题目描述
问题描述
在一个整数序列a1, a2, …, an中,如果存在某个数,大于它的整数数量等于小于它的整数数量,则称其为中间数。在一个序列中,可能存在多个下标不相同的中间数,这些中间数的值是相同的。
给定一个整数序列,请找出这个整数序列的中间数的值。
输入格式
输入的第一行包含了一个整数n,表示整数序列中数的个数。
第二行包含n个正整数,依次表示a1, a2, …, an。
输出格式
如果约定序列的中间数存在,则输出中间数的值,否则输出-1表示不存在中间数。
样例
样例输入
6
2 6 5 6 3 5
样例输出
5
样例说明
比5小的数有2个,比5大的数也有2个。
样例输入
4
3 4 6 7
样例输出
-1
样例说明
在序列中的4个数都不满足中间数的定义。
样例输入
5
3 4 6 6 7
样例输出
-1
样例说明
在序列中的5个数都不满足中间数的定义。
评测用例规模与约定
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ ai ≤ 1000。
笔记
见代码
代码
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n;
cin>>n;
int num[n];
for(int i=0;i<n;i++) cin>>num[i];
sort(num,num+n);
int mi=0,ma=0;
for(int i=0;i<n;i++){
if(num[i]<num[n/2]) mi++;
else if(num[i]>num[n/2]) ma++;
}
if(mi==ma){
if(n%2==0 && num[n/2]!=num[n/2-1]) cout<<-1;
else cout<<num[n/2];
}
else cout<<-1;
return 0;
}
2 201612-2 工资计算
题目描述
问题描述
小明的公司每个月给小明发工资,而小明拿到的工资为交完个人所得税之后的工资。假设他一个月的税前工资(扣除五险一金后、未扣税前的工资)为S元,则他应交的个人所得税按如下公式计算:
1) 个人所得税起征点为3500元,若S不超过3500,则不交税,3500元以上的部分才计算个人所得税,令A=S-3500元;
2) A中不超过1500元的部分,税率3%;
3) A中超过1500元未超过4500元的部分,税率10%;
4) A中超过4500元未超过9000元的部分,税率20%;
5) A中超过9000元未超过35000元的部分,税率25%;
6) A中超过35000元未超过55000元的部分,税率30%;
7) A中超过55000元未超过80000元的部分,税率35%;
8) A中超过80000元的部分,税率45%;
例如,如果小明的税前工资为10000元,则A=10000-3500=6500元,其中不超过1500元部分应缴税1500×3%=45元,超过1500元不超过4500元部分应缴税(4500-1500)×10%=300元,超过4500元部分应缴税(6500-4500)×20%=400元。总共缴税745元,税后所得为9255元。
已知小明这个月税后所得为T元,请问他的税前工资S是多少元。
输入格式
输入的第一行包含一个整数T,表示小明的税后所得。所有评测数据保证小明的税前工资为一个整百的数。
输出格式
输出一个整数S,表示小明的税前工资。
样例
样例输入
9255
样例输出
10000
评测用例规模与约定
对于所有评测用例,1 ≤ T ≤ 100000。
笔记
见代码注释
代码
/*
工资计算
3500保底
if t<3500 :t , a税后,A税前
else{//a=t-3500 是扣过税的部分
a>1500*97% ? a-=1500*97% ;ans=+1500;
a>3000*90% ? a-=3000*90%;ans+=3000;
a>4500*80% ? ......
a>26000*75% ?......
a>20000*70% ?......
a>25000*65% ? ......
ans += a/55%;
}
*/
#include<iostream>
using namespace std;
int t,ans=0,a;
bool total(int pri,double pect){
if(a>pri*pect) {
ans+=pri;
a-=pri*pect;
return true;
}
else ans+=a/pect;
return false;
}
int main(){
cin>>t;
if(t<=3500) ans=t;
else{
ans+=3500;
a=t-3500;
if(total(1500,0.97))
if(total(3000,0.90))
if(total(4500,0.80))
if(total(26000,0.75))
if(total(20000,0.70))
if(total(25000,0.65))
if(a) ans+=a/0.55;
}
cout<<ans;
return 0;
}
3 201612-3 权限查询
题目描述
问题描述
授权 (authorization) 是各类业务系统不可缺少的组成部分,系统用户通过授权机制获得系统中各个模块的操作权限。
本题中的授权机制是这样设计的:每位用户具有若干角色,每种角色具有若干权限。例如,用户 david 具有 manager 角色,manager 角色有 crm:2 权限,则用户 david 具有 crm:2 权限,也就是 crm 类权限的第 2 等级的权限。
具体地,用户名和角色名称都是由小写字母组成的字符串,长度不超过 32。权限分为分等级权限和不分等级权限两大类。分等级权限由权限类名和权限等级构成,中间用冒号“:”分隔。其中权限类名也是由小写字母组成的字符串,长度不超过 32。权限等级是一位数字,从 0 到 9,数字越大表示权限等级越高。系统规定如果用户具有某类某一等级的权限,那么他也将自动具有该类更低等级的权限。例如在上面的例子中,除 crm:2 外,用户 david 也具有 crm:1 和 crm:0 权限。不分等级权限在描述权限时只有权限类名,没有权限等级(也没有用于分隔的冒号)。
给出系统中用户、角色和权限的描述信息,你的程序需要回答多个关于用户和权限的查询。查询可分为以下几类:
* 不分等级权限的查询:如果权限本身是不分等级的,则查询时不指定等级,返回是否具有该权限;
* 分等级权限的带等级查询:如果权限本身分等级,查询也带等级,则返回是否具有该类的该等级权限;
* 分等级权限的不带等级查询:如果权限本身分等级,查询不带等级,则返回具有该类权限的等级;如果不具有该类的任何等级权限,则返回“否”。
输入格式
输入第一行是一个正整数 p,表示不同的权限类别的数量。紧接着的 p 行被称为 P 段,每行一个字符串,描述各个权限。对于分等级权限,格式为 :,其中 是权限类名, 是该类权限的最高等级。对于不分等级权限,字符串只包含权限类名。
接下来一行是一个正整数 r,表示不同的角色数量。紧接着的 r 行被称为 R 段,每行描述一种角色,格式为
<privilege 1> <privilege 2> …
其中 是角色名称, 表示该角色具有多少种权限。后面 个字符串描述该角色具有的权限,格式同 P 段。
接下来一行是一个正整数 u,表示用户数量。紧接着的 u 行被称为 U 段,每行描述一个用户,格式为
<role 1> <role 2> …
其中 是用户名, 表示该用户具有多少种角色。后面 个字符串描述该用户具有的角色。
接下来一行是一个正整数 q,表示权限查询的数量。紧接着的 q 行被称为 Q 段,每行描述一个授权查询,格式为 ,表示查询用户 是否具有 权限。如果查询的权限是分等级权限,则查询中的 可指定等级,表示查询该用户是否具有该等级的权限;也可以不指定等级,表示查询该用户具有该权限的等级。对于不分等级权限,只能查询该用户是否具有该权限,查询中不能指定等级。
输出格式
输出共 q 行,每行为 false、true,或者一个数字。false 表示相应的用户不具有相应的权限,true 表示相应的用户具有相应的权限。对于分等级权限的不带等级查询,如果具有权限,则结果是一个数字,表示该用户具有该权限的(最高)等级。如果用户不存在,或者查询的权限没有定义,则应该返回 false。
样例
样例输入
3
crm:2
git:3
game
4
hr 1 crm:2
it 3 crm:1 git:1 game
dev 2 git:3 game
qa 1 git:2
3
alice 1 hr
bob 2 it qa
charlie 1 dev
9
alice game
alice crm:2
alice git:0
bob git
bob poweroff
charlie game
charlie crm
charlie git:3
malice game
样例输出
false
true
false
2
false
true
false
true
false
样例说明
样例输入描述的场景中,各个用户实际的权限如下:
* 用户 alice 具有 crm:2 权限
* 用户 bob 具有 crm:1、git:2 和 game 权限
* 用户 charlie 具有 git:3 和 game 权限
* 用户 malice 未描述,因此不具有任何权限
评测用例规模与约定
评测用例规模:
* 1 ≤ p, r, u ≤ 100
* 1 ≤ q ≤ 10 000
* 每个用户具有的角色数不超过 10,每种角色具有的权限种类不超过 10
约定:
* 输入保证合法性,包括:
1) 角色对应的权限列表(R 段)中的权限都是之前(P 段)出现过的,权限可以重复出现,如果带等级的权限重复出现,以等级最高的为准
2) 用户对应的角色列表(U 段)中的角色都是之前(R 段)出现过的,如果多个角色都具有某一分等级权限,以等级最高的为准
3) 查询(Q 段)中的用户名和权限类名不保证在之前(U 段和 P 段)出现过
* 前 20% 的评测用例只有一种角色
* 前 50% 的评测用例权限都是不分等级的,查询也都不带等级
笔记
权限计算
数据结构:map<string,map<string,int> 两个map :角色权限表,用户权限表
1用户:n角色;1角色:n权限
1 读取并录入数据
map<string,int> m; //角色,权限等级
string 均为小写,
新的权限加入:权限默认-1 表示不分等级,否则判断权限录入 int
若权限名相同:判断并更新等级
2 检索并输出结果
不分等级 true/false
分等级带等级 true/false
分等级不带等级 (int)等级/否
使用count,返回的是被查找元素的个数。如果有,返回1;否则,返回0。注意,map中不存在相同元素,所以返回值只能是1或0。
使用find,返回的是被查找元素的位置,没有则返回map.end()。
代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<string>
using namespace std;
map<string,map<string,int> > map_role_pri;//角色权限表
map<string,map<string,int> > map_user_pri;//用户权限表
int p,r,u,q; //权限数,角色数,用户数,检索查询数
void getPri(string &s,string &cata,int &level){
cata=" ";
level=-1;
int i;
for(i=0;i<s.size() && s[i]!=':';i++) cata+=s[i];
if(s[i]==':') level=s[i+1]-'0';
}
int main(){
string s,user,role,cata;
int level,n;
map<string,int> m;
//录入 p 段 ,不做处理
cin>>p;
for(int i=0;i<p;i++) cin>>s;
//录入 r 段
cin>>r;
for(int i=0;i<r;i++){
cin>>role>>n;
while(n--){
cin>>s;
getPri(s,cata,level);
// cout<<s<<" "<<cata<< " "<<level<<endl;
if(level==-1) m[cata]=-1;
else m[cata]=m[cata]>level?m[cata]:level;
}
map_role_pri[role]=m;
m.clear();
}
//录入 u 段
cin>>u;
for(int i=0;i<u;i++){
map<string,int>::iterator it;
cin>>user>>n;
while(n--){
cin>>role;
for(it=map_role_pri[role].begin();it!=map_role_pri[role].end();it++){
if(it->second==-1) m[it->first]=-1;
else m[it->first]=m[it->first]>it->second?m[it->first]:it->second;
}
}
map_user_pri[user]=m;
m.clear();
}
//检索 q 段
cin>>q;
for(int i=0;i<q;i++){
cin>>user>>s;
getPri(s,cata,level);
//1 false:不存在用户,存在用户但无此权限,有此权限但级别不够高
if(map_user_pri.count(user)==0||map_user_pri[user].count(cata)==0
||map_user_pri[user][cata]<level) cout<<"false"<<endl;
//2 true:level!=-1 存在用户权限且权限够大,存在用户权限不分等级
else if(map_user_pri[user][cata]==-1 || (level!=-1 && map_user_pri[user][cata]>=level))
cout<<"true"<<endl;
//3 (int):level==-1, 存在用户 返回最大等级
else if(level==-1) cout<<map_user_pri[user][cata]<<endl;
}
return 0;
}