山东大学计算机科学与技术学院程序设计思维与实践模测
20210319A : R!!G!!B!!问题描述msy 的显示器被 yhf 借走了,于是 msy 需要一个新的显示器。他买来了许多 LED 小灯,每个小灯只能发出红、绿、蓝三种颜色光的其中一种。msy 需要三个不同颜色的小灯来拼成一个像素(像素之间并不能共用小灯),但是他并不知道每种颜色的小灯具体有多少个,只知道每个小灯的颜色。msy 想知道他用手头上的小灯可以拼出多少个像素,但是一个个数太麻烦
20210319
A : R!!G!!B!!
问题描述
msy 的显示器被 yhf 借走了,于是 msy 需要一个新的显示器。他买来了许多 LED 小灯,每个小灯只能发出红、绿、蓝三种颜色光的其中一种。msy 需要三个不同颜色的小灯来拼成一个像素(像素之间并不能共用小灯),但是他并不知道每种颜色的小灯具体有多少个,只知道每个小灯的颜色。msy 想知道他用手头上的小灯可以拼出多少个像素,但是一个个数太麻烦了,他希望你来用程序解决这个问题。
输入格式
第一行输入一个数 nn,表示所有小灯的数量。 第二行输入一个长度为 nn 的字符串,表示每个小灯的颜色。颜色使用R、G、B三种字母表示。
输出格式
输出一个整数,表示 msy 可以拼出的像素的个数。
样例输入
8 RGBRGBRG
样例输出
2
评测用例规模与约定
1≤n≤10^5
代码:
#include<bits/stdc++.h>
using namespace std;
int n;//小灯数量
int r = 0, g = 0, b = 0;
int main(){
scanf("%d",&n);
char *c = new char[n];
for(int i = 0; i < n; i++){
cin>>c[i];
if(c[i] == 'R') r++;
if(c[i] == 'G') g++;
if(c[i] == 'B') b++;
}
int result = 0;
result = min(r,g);
result = min(result,b);
printf("%d\n",result);
return 0;
}
B : 密码强弱度
题目描述
在很多的交互式网站中,都需要通过使用用户名与密码进行登录,为了正确的评估一个密码的强弱,机智的 lzh 想出了一个评价方案。 这里研究的密码只有数字与大小写字母组成。具体的评价方案如下:
-
如果一个密码的长度小于 66,则这个密码的强度为 00。
-
对于长度大于等于 66 的密码,根据字符的种类(字符分为三类:数字,小写字母,大写字母),将连续的同种类的密码划分为一段,其段数即为密码的强弱程度。例如,密码
asd123As2d可以分为asd、123、A、s、2、d6段,所以这个密码的强度为6。
输入描述
输入一行一个字符串 s,1≤∣s∣≤10^6,表示密码。
输出描述
输出一行一个整数,表示密码的强弱程度。
Input
1VIpuVNOv8
Output
6
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n = 0;//密码强度
string s;
cin>>s;
int len = s.size();
if(len <= 6) n = 0;
else{
int temp1 = 0, temp2 = 0; //1表示小写字母,2表示大写字母,3表示数字
for(int i = 0; i < len; i++){
if(s[i] >= '0' && s[i] <= '9'){
temp1 = temp2;
temp2 = 3;
}
if(s[i] >= 'A' && s[i] <= 'Z'){
temp1 = temp2;
temp2 = 2;
}
if(s[i] >= 'a' && s[i] <= 'z'){
temp1 = temp2;
temp2 = 1;
}
if(temp1 != temp2) n++;
}
}
printf("%d\n",n);
return 0;
}
C : 拉面馆
题目描述
TT 的家门外有一家味道很好的拉面馆,每天都有很多人在拉面馆内喝拉面。拉面有 k种配料,分别记为 1,2,..., k每种配料都有着独特的风味。为了应对短时间内大量人群用餐需求,面馆的老板会在有客人到来之前,提前做好配有各种配料的拉面 n碗(之后不再制作新的拉面),每碗面都会有 k 种配料中的一种或多种。每一碗面都有一个制作完成的时间点 t_i,每碗面的制作完成的时间点都是唯一的。
有 m位客人陆续到店吃面,第 i位客人在 s_i时间到店,且有自己喜爱的一些配料 c_1,...,c_Ci,也就是说,这位客人会买一份至少含有配料 c_1,...,c_Ci 的面(可以含有其他种类的配料,但不能缺少喜爱的配料)。当满足条件的面有很多碗时,这位客人会挑选完成时间距离自己的到店时间最近的面,若这碗面是第j碗,则顾客会产生 s_i - t_j的不满意度;当含有c_i的面不存在时,顾客会直接愤怒离开。
今天热心的 TT 要帮老板记录客人的情况,请你帮他写一个程序完成上述要求。
输入描述
输入的第一行三个数 n, m, k(1≤n,m≤2×10^5,1≤k≤3),分别表示制作的面的数量,顾客的数量与配料的种类数。
接下来一行 n个数,表示 t_i,保证输入的 t_i是递增的。 接下来 n行,表示每碗面含有的材料。第一个数字为 K_i(Ki≥1) 表示第i碗面中含有的配料的种类数,接下来K_i个数,表示这碗面含有的配料编号,保证编号不会重复。
接下来一行m个数,表示s_i,保证s_i是递增的,且∀i,j,1≤t_i<s_j≤109。 接下来m行,表示每位顾客的喜好。第一个数字为 C_i(C_i≥1) 表示第i个顾客喜爱配料的种类数,接下来C_i个数,表示顾客喜爱的配料编号,保证编号不会重复。
输出描述
输出包含m行,每行表示一个顾客的状态,若顾客吃到了面,则输出顾客的不满意度;若顾客愤怒离开,则输出Angry。
子任务
存在 20%的数据,满足 k=1; 存在 30% 的数据,满足 n,m*≤5000; 存在 30% 的数据,满足 k=2;
提示
可以尝试使用二进制位表示每种配料的有无。
Input
14 14 3 3 4 12 15 23 26 28 30 33 34 37 41 43 45 1 1 1 2 2 1 3 2 1 3 2 1 2 2 1 2 1 1 2 1 3 2 1 2 2 1 3 3 1 2 3 1 3 2 1 3 1 2 59 61 62 63 66 72 80 83 88 91 92 95 96 99 1 2 1 1 2 1 3 2 1 3 1 2 1 3 3 1 2 3 2 1 3 2 1 3 2 1 2 2 1 3 1 3 2 1 2 1 1
Output
14 18 25 29 33 31 Angry 53 73 65 80 Angry 73 71
代码:
#include<bits/stdc++.h>
using namespace std;
set<int> st[8]; //配料集合 二进制表示
int main(){
// freopen("test.txt","r",stdin);
// freopen("a.out","w",stdout);
int n,m,k; //n制作的面的数量,m顾客的数量,k配料的种类数
scanf("%d%d%d",&n,&m,&k);
int *t = new int[n]; //每碗面完成的时间点
int *s = new int[m]; //每位客人来的时间
int *a = new int[n]; //第i碗的配料种类数
int *b = new int[m]; //第i个客人的配料种类数
for(int i = 0; i < n; i++){
scanf("%d",&t[i]);
}
for(int i = 0; i < n; i++){
int v = 0;
scanf("%d",&a[i]); //第i碗面含有的配料的种类数
for(int j = 0; j < a[i]; j ++){
int temp; //表示第几种配料
scanf("%d",&temp);
v |= (1 << (temp-1)); //二进制存储
}
for(int j = 1; j < 8; j++){
if((v & j) == j)
st[j].emplace(t[i]); //所有的包含j的方案种类
}
}
for(int i = 0; i < m; i++){
scanf("%d",&s[i]);
}
for(int i = 0; i < m; i ++){
scanf("%d",&b[i]);
int v = 0;
for(int j = 1; j <= b[i]; j++){
int temp;
scanf("%d",&temp);
v |=(1<< (temp - 1));
}
if(st[v].empty())
printf("Angry\n");
else{
int vv = *st[v].rbegin(); //反向迭代器
printf("%d\n",s[i] - vv);
for(int j = 1; j < 8; j++)
st[j].erase(vv);
}
}
return 0;
}
20210402
A : 时间复杂度
问题描述
分析算法的时间复杂度是评价算法性能的重要方式之一,对于同一问题来说,拥有线性时间复杂度的算法往往比拥有平方级别时间复杂度的算法要快很多,因此拥有线性时间复杂度的算法往往优于拥有平方级别时间复杂度的算法。
通常,可以根据输入n的值确定算法的运行时间,n可以表示要排序的对象数,多边形顶点数等等。现给出一段简易的程序,程序规则如下,其中<number>可以是任何非负整数:
< Program > ::= "BEGIN" < Statementlist > "END" < Statementlist > ::= < Statement > | < Statement > < Statementlist > < Statement > ::= < LOOP-Statement > | < OP-Statement > < LOOP-Statement > ::= < LOOP-Header > < Statementlist > "END" < LOOP-Header > ::= "LOOP" < number > | "LOOP n" < OP-Statement > ::= "OP" < number >
针对该规则下的程序的运行时间可以如下计算:执行OP语句所花费的时间与其参数指定的时间相同(即为number)。LOOP语句到其对应的END之间所有语句执行的次数与LOOP后的参数相同(即为number或n)。程序运行时间是其组成部分的时间总和。因此,总运行时间通常取决于n。
输入格式
输入一段程序,空格和换行符可以出现在程序中的任何位置,但不能出现在关键字BEGIN,END,LOOP和OP中或整数值中。LOOP的循环嵌套深度最多为10。
输出格式
以n为单位输出程序的运行时间,即输出一个化简后的Y(Y<=10)次多项式,形如“Runtime = a*n^10+b*n^9+...+i*n^2+ j*n+k”,若n的某一项系数为0则直接省略该项,若系数为1则省略其系数。 如果运行时间为0,则只需打印 “Runtime = 0”。
样例输入
BEGIN
LOOP n
LOOP n
OP 3
OP 4
LOOP 4
OP 3
END
END
END
OP 7
END
样例输出
Runtime = 19*n^2+7
样例说明
Runtime = n(n(3+4+4*3))+7=19*n^2+7
数据范围说明
LOOP循环嵌套深度<=10且关键字总数不超过50 且所有运算均在int范围内进行 对于测试点1,保证只包含OP语句 对于测试点2,3,保证只有一段Statement list且只有一层循环 对于测试点4,保证只有一段Statement list
代码:
#include<bits/stdc++.h>
using namespace std;
//字符串转数字 string 转 int
int string_to_int(string s){
int length = s.size();
int ans = 0;
for(int i = 0; i < length; i++){
ans =ans * 10 + (int)(s[i] - '0');
}
return ans;
}
bool solve(int *a){
char s[50];
cin >> s;
switch (s[0]){
case 'E':{ //END
return 0;
}
case 'B':{ //BEGIN
while(solve(a)); //若因OP返回,则继续;若因END返回,则结束
break;
}
case 'O':{ //OP
cin >> s;
a[0] += string_to_int(s);
return solve(a);
break;
}
case 'L':{ //LOOP
int temp[11] = {0};
cin >> s;
while(solve(temp));
if(s[0] == 'n'){//表达式乘n则所有项的次数+1
for(int i = 10; i > 0; i--){
temp[i] = temp[i-1];
}
temp[0] = 0;
}
else{
int x = string_to_int(s);
for(int i = 0; i < 11; i++)
temp[i] *= x; //表达式乘以一个常数,则所有项的系数乘以该常熟
}
for(int i = 0; i < 11; i++)
a[i] += temp[i];
break;
}
default:
break;
}
return 1;
}
int main(){
freopen("test.txt","r",stdin);
int a[11] = {0}; //指数为i的项,其系数为a[i]
printf("Runtime = ");
solve(a);
bool flag = 0;
bool before = 0; //标记输出当前项之前是否输出过前面的项
for(int i = 10; i >= 0; i--){
if(a[i] != 0){ //当系数不等于0时,才输出该项
flag = true;
if(before){
printf("+"); //输出过前面的项,因此要输出‘+’
before = 0;
}
if(i == 0){ //指数取0时,直接输出该数字
printf("%d",a[i]);
before = 0;
}
else{
bool flag = false; //标记系数是否为1
if(i && a[i] != 1){ //指数不为0且系数不为1
flag = 1;
printf("%d",a[i]);
before = 1;
}
if(i != 0){ //当指数不为0时
if(flag) //如果系数不为1
printf("*");
printf("n");
if(i != 1)
printf("^%d",i); //输出指数
before = 1;
}
}
}
}
if(!flag)
printf("0\n");
return 0;
}
20210416
A : TT 的袜子
题目描述
TT 有一屋子的袜子,总共有 nn 只,袜子有 kk 种颜色,每天 TT 都要穿两只颜色相同的袜子,这一天结束后 TT 会丢弃今天的袜子。
现在输入所有袜子的颜色,输出 TT 的袜子可以坚持用多少天。
输入描述
第一行输入 n, kn,k (1\leq n, k \leq 10001≤n,k≤1000)。 第二行输入 nn 个数,第 ii 个数 c_ic**i 表示第 ii 只袜子的颜色(1\leq c_i \leq k1≤c**i≤k)。
输出描述
输出一个数,表示答案。
输入样例
10 5 1 2 1 3 1 5 4 4 2 2
输出样例
3
代码:
#include<bits/stdc++.h>
using namespace std;
int n,k;
int c[1010];
int color_num[1010] = {0};
int color_;
int main(){
scanf("%d%d", &n,&k);
for(int i = 0; i < n; i ++){
scanf("%d", &color_);
color_num[color_] ++;
}
int sum = 0;
for(int i = 1; i <= k; i ++){
color_num[i] = color_num[i] / 2;
sum = sum + color_num[i];
}
printf("%d",sum);
return 0;
}
B : 定价
题目描述
有 nn 个人买东西同一个商品,第 ii 个人认为合理的价格区间 l_i,r_i,表示如果价格低于 ll 嫌便宜,如果价格高于 rr 嫌贵。
请你设计商品的价格,使在满足尽可能多的人认为价格合理的条件下,商品价格最高。具体来说,你需要输出最终商品的定价与认为价格合理的人数。
输入描述
第一行输入一个整数 n(1\leq n \leq 10^6)n(1≤n≤106),表示人数。 接下来 nn 行,第 ii 行输入两个数 l_i, r_il**i,r**i (1\leq l_i \leq r_i \leq 10^6)(1≤l**i≤r**i≤106),表示第 ii 个人认为的价格合理的区间。
输出描述
输出一行两个整数,以一个空格分割,分别表示最终商品的定价与认为价格合理的人数。
输入样例
5 1 3 2 4 2 3 3 4 4 5
输出样例
3 4
子任务
存在 70\%70% 的测试数据,n \leq 1000 \ ,\ \ \forall i, l_i \leq r_i \leq 1000n≤1000 , ∀i,l**i≤r**i≤1000
对于所有的测试数据,1\leq n \leq 10^61≤n≤106,\forall i, 1\leq l_i \leq r_i \leq 10^6∀i,1≤l**i≤r**i≤106
代码:
#include<bits/stdc++.h>
using namespace std;
int price[1000100] = {0};
int main(){
int l;
int r;
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d%d",&l,&r);
price[l]++;
price[r+1]--;
}
int maxnum = 0;
int suitprice = 0;
for(int i = 1; i < 1000100; i++){
price[i] = price[i-1] +price[i];
if(price[i] >= maxnum){
maxnum = price[i] ;
suitprice = i;
}
}
cout << suitprice <<" "<<maxnum;
}
C : 吃包子
问题描述
来来来,尝尝新出炉的包子啊! 小 \text{L}L 和小 \text{W}W 买了 nn 个包子排成一行,用 s_is**i 表示第 ii 个包子的大小,并且包子大小最大值是 xx。 小 \text{W}W 是个挑剔的人,小 \text{W}W 只肯按照包子大小不递减的顺序吃包子。 现在小 \text{L}L 会负责吃掉大小 s_is**i 处在 l,r 范围内的所有的包子,之后小 WW 会按照包子标号从小到大依次吃掉剩下的包子,如果剩下的包子没有满足不递减的顺序,小 \text{W}W 会不肯吃。 现在小 \text{L}L 想知道有多少种 l,r 的方案可以让小 \text{W}W 肯吃包子。 一个合法的 l,r ,ll 和 rr 必须都是 1\le l\le r\le x1≤l≤r≤x 的整数
输入格式
第一行一个整数 n,xn,x ,表示有 nn 个包子,包子的最大大小为 xx。 1\le n,x\le10^61≤n,x≤106 接下来一行,有 nn 个数,第 ii 个数 s_is**i 表示第 ii 个包子的大小。 1\le s_i\le x1≤s**i≤x
输出格式
输出一行,一个整数表示方案数。
样例输入
5 4 1 3 2 4 2
样例输出
7
样例解释
1,2 : 去掉数值处在范围 1,2 的数值之后,剩余数列为 {3,4}{3,4} ,是非递减数列 1,3 : 去掉数值处在范围 1,3 的数值之后,剩余数列为 {4}{4} ,是非递减数列 1,4 : 去掉数值处在范围 1,4 的数值之后,剩余数列为 {}{} ,是非递减数列 2,2 : 去掉数值处在范围 2,2 的数值之后,剩余数列为 {1,3,4}{1,3,4} ,是非递减数列 2,3 : 去掉数值处在范围 2,3 的数值之后,剩余数列为 {1,4}{1,4} ,是非递减数列 2,4 : 去掉数值处在范围 2,4 的数值之后,剩余数列为 {1}{1} ,是非递减数列 3,4 : 去掉数值处在范围 3,4 的数值之后,剩余数列为 {1,2,2}{1,2,2} ,是非递减数列 共有 77 种方案。
数据范围
对于 30\%30% 的数据,满足 1\le n,x\le 5001≤n,x≤500 对于 80\%80% 的数据,满足 1\le n,x\le 50001≤n,x≤5000 对于 100\%100% 的数据,满足 1\le n,x\le 10^61≤n,x≤106
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxX = 1e6 + 10;
int n, x;
int a[maxX];
int L[maxX],R[maxX];
int preL[maxX],preR[maxX];
//矛盾的数的并
int sufL[maxX],sufR[maxX];
//选取后面若干个数和他矛盾的组成的一个总的集合
void init(){
for(int i = 0; i <= x+1; i++){
L[i] = preL[i] = sufL[i] = x+1;
R[i] = 0, preR[i] = 0, sufR[i] = 0;
}
set<int> s;
//从左到右处理,在数字t前面且比t大的值
for(int i = 1; i <= n; i++){
int t = a[i];
//查找前面那些数中第一个比它大的数
auto it = s.upper_bound(t);
if(it == s.end()){
s.insert(t);
continue;
}
else{
L[t] = min(L[t],*it);
R[t] = max(R[t],*s.rbegin());
}
s.insert(t);
}
set<int, greater<int> > s2;
for(int i = n; i >=1; i--){
int t = a[i];
auto it = s2.upper_bound(t);
if(it == s2.end()){
s2.insert(t);
continue;
}
else{
L[t] = min(L[t],*s2.rbegin());
R[t] = max(R[t],*it);
}
s2.insert(t);
}
//求前面区间的并和后面区间的并
for(int i = 1; i <= x; i++){
preL[i] = min(preL[i - 1], L[i]);
preR[i] = max(preR[i - 1], R[i]);
}
for(int i = x; i >= 1; i--){
sufL[i] = min(sufL[i + 1],L[i]);
sufR[i] = max(sufR[i + 1],R[i]);
}
}
bool check(int i, int m){
if(m <= preR[i]) return false; //m和前i个数矛盾
if(m <= sufR[m]) return false; //m和自己后面那些数矛盾
if(i >= sufL[m]) return false; //i和m后面的那些数矛盾
return true;
}
int main(){
cin >> n >> x;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
//cout <<"x:"<<x;
init();
long long ans = 0;
for(int i = 0; i < x; i++){
if( i >= preL[i]) //与前面的矛盾区间本身就矛盾
break;
int l = i + 1, r = x+1;
//cout <<"l:" <<l <<"r:"<<r;
while(r> l + 1){
int m = (l + r) >> 1;
if(check(i,m)) r = m; //删除i到m这段合法
else l = m;
}
ans += x + 1 - l;
}
cout << ans;
return 0;
}
20210430
A : 逻辑表达式
题目描述
在山的那边海的那边,有一群蓝精灵,他们活泼又聪明,他们……偶然有一天发现了一组神奇的逻辑表达式,这组表达式可以表示数字x处于的范围。 例如 x >= 3 && x <= 5 || x >= 8 && x <= 11 || x >= 7 || x <= 0 可是蓝精灵们觉得这样的表达式过于冗杂了,他们立志要不破坏x表达范围的同时将表达式简化,使这组表达式出现的与x比较的整数常量尽可能少。 蓝精灵们发现了一个秘密,x一定是[-32768,32767]内的数字。
输入
输入包含T行。 每一行有一个或两个比较表达式组成,由运算符"&&“分隔,每个比较都是以"x"开头,后面是操作符”>=“或”<=",再后面是一个整型常量。当一行中包含两个比较时,第一个总是">="。 除了最后一行之外,所有行都由运算符"||“结尾。一行中的每个符号都由一个空格隔开(”>=“是一个符号,”<="同理),行首和行尾没有多余的空格。
输出要求
输出包含若干行,格式与输入格式相同,按照表达式中数字的大小从小到大输出。对所有整数x产生与输入表达式相同的比较结果,在其文本中包含尽可能少的行数。 注意,题目默认x>=-32768 && x<=32767。特别地,如果表达式对[-32768,32767]内所有整数都为真,则写一行单词"true"。如果表达式对[-32768,32767]内所有整数都为假,则写一行单词"false"。 如果某个区间内只包含一个常数c,则输出"x >= c && x <=c"。
样例1
样例输入:
x >= 3 && x <= 5 || x >= 8 && x <= 11 || x >= 7 || x <= 0
样例输出:
x <= 0 || x >= 3 && x <= 5 || x >= 7
样例2
样例输入:
x >= 5 && x <= 3
样例输出:
false
样例3
样例输入:
x <= 5 || x >= -3
样例输出:
true
样例4
样例输入:
x >= -32768 && x <= 0 || x <= 0
样例输出:
x <= 0
数据范围 对于30%的数据,1<=T<=100 对于100%的数据,1<=T<=1000,所有数据绝对值<=100000
代码:
#include<bits/stdc++.h>
using namespace std;
int le,ra;
int maxnum=INT_MAX;
int minnum=-INT_MAX;
struct lr_block{
int ll;
int rr;
bool flag;
lr_block(int a,int b){ll = a; rr = b; flag = 1;}
};
vector<lr_block> v;
vector<lr_block> res;
bool cmp(lr_block a,lr_block b){
return a.ll < b.ll;
}
void solve(int i,bool k){
if(i==v.size()){
if(k){
lr_block temp_block(le,ra);
res.push_back(temp_block);
maxnum=min(maxnum,le);
minnum=max(minnum,ra);
}
return ;
}
if(!v[i].flag) {
solve(i+1,k);
return;
}
if(k==false){
le=v[i].ll;
ra=v[i].rr;
solve(i+1,true);
return;
}
if(v[i].ll<=ra+1&&v[i].ll>=le){
le=min(le,v[i].ll);
ra=max(ra,v[i].rr);
solve(i+1,true);
}
else{
lr_block tempblock(le,ra);
res.push_back(tempblock);
maxnum=min(maxnum,le);
minnum=max(minnum,ra);
le=v[i].ll;ra=v[i].rr;
solve(i+1,true);
}
}
int main(){
string input;
while(getline(cin,input)){
istringstream ss(input);
vector<string> vts;
string temps;
int n=0;
while(ss>>temps){
vts.push_back(temps);
n++;
}
if(n==8||n==7){
lr_block temp_block(stoi(vts[2]),stoi(vts[6]));
v.push_back(temp_block);
}
else{
if(vts[1]=="<="){
lr_block temp_block(-32768,stoi(vts[2]));
v.push_back(temp_block);
}
if(vts[1]==">="){
lr_block temp_block(stoi(vts[2]), 32767);
v.push_back(temp_block);
}
}
if(n % 2 == 1 )
break;
}
sort(v.begin(),v.end(),cmp);
for(int i = 0; i < v.size(); i++){
if((v[i].ll>v[i].rr)||v[i].rr<-32768||v[i].ll>32767)
v[i].flag = 0;
}
solve(0,false);
if(res.size()==0)
printf("false");
else if(res.size() == 1 && maxnum == -32768 && minnum == 32767){
printf("true");
return 0;
}
for(int i=0; i < res.size(); i++){
int l = res[i].ll,r=res[i].rr;
l=max(l,-32768);
r=min(r,32767);
if(i != 0){
printf(" ||\n");
}
if(l==-32768){
printf("x <= %d",r);
continue;
}
else if(r==32767){
printf("x >= %d",l);
continue;
}
cout<<"x >= "<<l<<" && x <= "<<r;
}
return 0;
}
20210528
A : 小H爱数学
问题描述
小H最近喜欢上了数学,她认为幂运算是一种优美的运算。现在对于给定的一个区间[l,r],她想知道有多少k的幂次在此区间之中,你能帮帮她吗
输入格式
输入一行三个正整数,依次为l,r,kl,r,k
输出格式
输出幂值在[l,r]的所有k的非负整数幂,如果没有请输出-1。为了方便测试,请保证输出从小到大
样例1 输入
1 10 2
样例1 输出
1 2 4 8
样例2 输入
2 4 5
样例2 输出
-1
数据规模和约定
1 ≤ ll ≤ rr ≤ 10^{18}1018, 2 ≤ kk ≤ 10^9109
代码:
#include<bits/stdc++.h>
using namespace std;
long long l,r,k;
vector<long long> vv;
int main(){
scanf("%lld%lld%lld",&l,&r,&k);
bool flag = 1;
for(int i = 0; i < 70; i++){
long long temp = pow(k,i);
if(temp >= l && temp <= r){
cout << temp <<" ";
flag =0;
}
if(temp > r)
break;
}
if(flag) printf("-1\n");
return 0;
}
B : 山脉高度
题目描述
LZH最近发现一些山脉正在不断增高,经过其长时间的观察,LZH发现了山脉高度变化的规律:
-
山脉群总体是一个N*M的矩形,每个山脉都有自己的高度,不同山脉的高度可以相同
-
每次山脉高度发生增长都是一个长度L(L \leq NL≤N),宽度为W(W \leq MW≤M)的矩形内的所有山脉共同增加高度 C
经过这一段时间的观察,LZH记录下了一共n次山脉高度的增长。
现在LZH拥有山脉群的初始高度,问经过这n次增长后,山脉群的高度是多少?
输入描述
第一行输入两个整数N,M,表示山脉群的大小
接下来N行,每行M个整数,第ii行,第jj列表示位于i,j的山脉的初始高度a_{ij}aij。
接下来输入一个整数n,表示LZH一共记录下来的山脉增长的次数
接下来n行,每行5个整数lx,ly,rx,ry,Cl**x,l**y,r**x,r**y,C, lx,lyl**x,l**y表示所要增长的矩形的左上角,rx,ryr**x,r**y表示所要增长的矩形的右下角,CC表示增加的高度
输出描述
输出共N行,M列
输出经过n次增长后的N*M的矩形山脉群的高度
输入样例
3 3 1 1 1 1 1 1 1 1 1 3 1 1 2 2 1 2 2 3 3 1 2 1 3 2 1
输出样例
2 2 1 3 4 2 2 3 2
数据范围
70%数据 1 \leq N,M \leq 100, 0 \leq a_{ij} \leq 1001≤N,M≤100,0≤aij≤100 ,1\leq n \leq 1001≤n≤100 ,1\leq lx \leq rx \leq N,1\leq ly \leq ry \leq M,1 \leq C \leq 1001≤l**x≤r**x≤N,1≤l**y≤r**y≤M,1≤C≤100
100%数据 1 \leq N,M \leq 2000, 0 \leq a_{ij} \leq 10001≤N,M≤2000,0≤aij≤1000 ,1\leq n \leq 10001≤n≤1000 ,1\leq lx \leq rx \leq N,1\leq ly \leq ry \leq M,1 \leq C \leq 10001≤l**x≤r**x≤N,1≤l**y≤r**y≤M,1≤C≤1000
代码:
#include<bits/stdc++.h>
using namespace std;
int N,M;
int n;
int a[2005][2005];
int b[2005][2005];
int lx,ly,rx,ry,c;
int main(){
scanf("%d%d",&N,&M);
for(int i = 1; i <= N; i++)
for(int j = 1; j <= M; j++)
scanf("%d",&a[i][j]);
for(int i = 1; i <= N; i ++)
for(int j = 1; j <= M; j++)
b[i][j] = a[i][j] - a[i][j-1];
scanf("%d",&n);
for(int i = 0; i < n; i++){
scanf("%d%d%d%d%d",&lx,&ly,&rx,&ry,&c);
for(int x = lx; x <= rx; x++){
b[x][ly] += c;
b[x][ry + 1] -=c;
}
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= M; j++){
a[i][j] = a[i][j-1] + b[i][j];
printf("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
C : 后端测试
题目背景
明天就是全国软件大赛的决赛答辩了!经过几天的通宵,YHF终于写好了他的后端代码!他倒在椅子上,睡得很安详,嘴角还有一丝微笑……
但是后端还有一项工作要做,那就是测试后端程序的运行速度。其他队员对于YHF的代码完全不了解,因此无从下手。旁边的SYS看不下去了,决定帮帮他们。在凌乱的草稿纸堆中,SYS发现YHF已经做过了一些速度测试,但是还没有整合起来,而且YHF的后端设计非常复杂,每个服务器都有一个任务集群,每个任务还可能会调用其他服务器的任务集群……SYS花了好长时间,才把任务与服务器之间的关系整理好,但是速度测试怎么也做不出来了。他找到了代码水平更高的你,希望你来解决速度测试的问题。
题目描述
YHF的后端有若干个服务器,每个服务器上有若干个任务组成任务集群。任务分为两类,一类是计算任务,它的运行时间是固定的;一类是调用任务,它会启动另一个服务器的任务集群,并等待这个服务器的所有任务执行完成,由于通信延迟,这类任务的实际运行时间还要加一秒。对于一个服务器,它的任务之间可能存在一些依赖关系,一个任务只有当它的所有依赖任务都执行完成后才能执行。YHF的服务器性能非常强大,只要任务的所有依赖执行完成就可以立即开始运行。同时,YHF保证任务之间没有环形的依赖关系或调用关系。
通过YHF的草稿,SYS已经了解到所有计算任务的执行时间、所有调用任务的跳转链接以及所有任务的依赖。现在需要你回答YHF的队员抛出的问题:某个服务器的任务集群需要多长时间才能完成?
输入格式
第一行两个数字 n,mn,m ,表示服务器的数量和询问数量。服务器的标号是从 11 到 nn 的。
接下来输入每个服务器的信息,首先是一个整数 kk,表示这个服务器有 kk 个任务。任务的标号是从 11 到 kk 的。接下来的 k2k∗2 行表示 kk* 个任务的信息,每个任务占两行,第一行的第一个数 ll 表示它的依赖数量,接着 ll 个数表示它依赖的任务的标号;第二行是两个数字,第一个数表示任务类型,如果为 00 表示这个任务是计算任务,此时第二个数字表示运行时间,如果为 11 表示这个任务是调用任务,此时第二个数字表示调用的服务器编号。
接下来 mm 行,每行一个整数 qq,表示询问的服务器编号。
输出格式
输出 mm 行,第 ii 行表示第 ii 个询问的服务器的运行时间。保证结果在 10^{18}1018 以内。
样例输入
3 3 1 0 0 100 2 0 0 10 1 1 1 1 5 0 0 1 1 1 1 1 1 1 1 2 0 0 100 3 2 3 4 0 1 1 2 3
样例输出
100 111 114
样例解释
如图所示,绿色数字是运行时间,绿色箭头是调用关系。
数据规模与子任务
| 数据点 | nn | kk | 其他约束条件 |
|---|---|---|---|
| 1, 21,2 | 11 | 100100 | 所有任务都是计算任务 |
| 3, 43,4 | 10^4104 | 100100 | 所有任务都是计算任务 |
| 5, 65,6 | 10^4104 | 11 | 无 |
| 7, 8, 9, 107,8,9,10 | 10^4104 | 100100 | 无 |
代码:
#include "bits/stdc++.h"
using namespace std;
typedef long long ll; //10^18
struct server{ //服务器
int n; //任务个数
vector<vector<int>> e; //存边的信息
vector<ll> t,d; //本来的运行时间t,结果d(状态)到这个地方运行了多长时间
vector<int> rd; //入度数量的数组
server(){}
server(int n):n(n){ //初始化
e.resize(n+1);
t.resize(n+1);
d.resize(n+1);
rd.resize(n+1);
}
void add_edge(int u, int v) { //加边的函数 从u到v的边,u依赖v。
e[u].push_back(v);
rd[v]++; //入度数量加加
}
ll run() { //求运行时间 拓扑排序
queue<int> q;
for(int i = 1; i <= n; i++) {
if(rd[i] == 0) q.push(i), d[i] = t[i];
}
while(q.size()) {
int x = q.front(); q.pop();
for(int y:e[x]) {
d[y] = max(d[y],d[x]+t[y]); //更新
rd[y]--;
if(rd[y] == 0) q.push(y);
}
}
return *max_element(d.begin(), d.end());
}
};
vector<server> s(1); //存服务器信息,从编号1开始存
vector<ll> ans; //记录询问结果
ll dfs(int x) {
if(ans[x] >= 0) return ans[x];
for(ll &t:s[x].t)
if(t < 0) t = dfs(-t) + 1; //调用任务 服务器延时+1
return ans[x] = s[x].run();
}
int main()
{
int n,m; //服务器数量,询问数量
cin >> n >> m;
ans.resize(n+1,-1);
for(int i = 1, k; i <= n; i++){
cin>>k; //k个任务
s.emplace_back(k);
for(int u = 1,l,op,t; u <= k; u++) {
cin>>l; //依赖的任务数量
for(int j = 0,v; j < l; j++) {
cin>>v; //l个数,表示依赖的任务编号
s[i].add_edge(v,u); //u依赖于v
}
cin>>op>>t; //任务类型
if(op==0) s[i].t[u] = t; //计算任务 运行时间
else s[i].t[u] = -t; //调用任务 负数表示,调用服务器的编号为t
}
}
while(m--) {
int x;
cin>>x; //询问 服务器编号
cout<<dfs(x)<<endl;
}
return 0;
}
20210604
A : 成绩计算
题目描述
大一大二的每学期都有体育课,为了进一步改进体育课程,老师想出了全新的体育考核方式。
体育课的成绩由五部分组成:
-
体育课专项成绩(满分 5050 分)
-
体育课专项(如羽毛球,篮球,足球等)成绩将由任课体育老师直接给出。
-
-
长跑测试成绩(满分 2020 分)
-
长跑测试成绩将由期末长跑测试确定,其中男生需进行 30003000 米测试,女生需进行 15001500 米测试,具体评分标准为:
20 18 16 14 12 10 8 6 4 2 男生 12'30" 13'00" 13'30" 14'00" 14'30" 15'10" 15'50" 16'30" 17'10" 18'00" 女生 6'40" 6'57" 7'14" 7'31" 7'50" 8'05" 8'20" 8'35" 8'50" 9'00"
-
-
日常长跑成绩(满分 1010 分)
-
日常长跑成绩是通过手机 App 来记录同学们的课外长跑情况,根据对原始跑步数据进行筛选,得到课外长跑的合法次数,来最终确定此部分的成绩。
一条合法的锻炼记录需同时满足:
-
男生长跑距离 30003000 米以上(包含 30003000 米),女生长跑距离 15001500 米以上(包含 15001500 米);
-
平均速度(运动距离/(结束时间-开始时间))不慢于 22 米/秒,且不快于 55 米/秒;
-
总暂停时间不得超过 44 分 3030 秒;
-
平均步幅(距离/步数)不超过 1.51.5 米;
-
开始时间需与同一天中的上条合法记录的结束时间间隔 66 小时以上(包含 66 小时);
日常长跑成绩的合法次数与该部分得分的对应如下:
分数 10 9 8 7 6 4 2 次数 [21,,+∞) [19,20] [17,18] [14,16] [11,13] [7,10] [3,6] -
-
-
体测成绩(满分 1010 分)
-
对于体测部分,若达到合格标准则得到该部分满分 1010 分,否则该部分不得分。
-
-
平时成绩(满分 1010 分)
-
平时成绩的 1010 分由两部分组成:出勤次数占 55 分,日常表现分数占 55 分。
其中出勤次数为课程的到课次数和日常长跑的合法次数之和,出勤得分与出勤次数的对应如下:
分数 55 44 33 22 11 次数 [18,+∞) [15,17] [12,14] [9,11] [6,8] 日常表现分数由老师直接给出。
-
不难看出,要想准确无误地计算出每个人的体育成绩并不是一件轻松的事,于是体育部的老师找到了你,他将提供所有需要用到的数据,希望你帮他算算所有同学体育总评成绩及等级。
百分制成绩与等级、绩点对应如下:
| A | A- | B+ | B | B- | C+ | C | C- | D+ | D | F |
|---|---|---|---|---|---|---|---|---|---|---|
| [95, 100] | [90, 95) | [85, 90) | [80, 85) | [77, 80) | [73, 77) | [70, 73) | [67, 70) | [63, 67) | [60, 63) | [0, 60) |
输入格式
输入第一行,包含一个正整数 nn,表示学生人数。
接下来 nn 行,每行表示一位学生(按学号字典序给出),各项数据之间用空格隔开,一位学生的数据包括:
-
一个长度为 1010 的正整数 pp(数据保证不包含前导零),表示第 ii 位同学的学号;
-
一个字符,
M或F,若为M表示第 ii 位同学为男生,若为F则表示第 ii 位同学为女生; -
一个介于 00 到 5050 之间的非负整数 ss,表示第 ii 位同学的体育课专项成绩;
-
一个形如
a'b"的字符串,表示第 ii 位同学的期末长跑测试成绩为 aa 分 bb 秒; -
一个字符,
P或F,若为P表示第 ii 位同学的体质测试通过,若为F则表示第 ii 位同学的体质测试没有通过; -
一个介于 00 到 55 之间的非负整数 ff,表示第 ii 位同学的日常表现分数;
-
一个非负整数 cc,表示第 ii 位同学的到课次数。
接下来一行,包括一个非负整数 mm,表示需要筛选的日常长跑数据条数。
接下来 mm 行,每行表示一条需要筛选的日常长跑数据(按开始时间顺序给出),各项之间用空格隔开,一条数据包括:
-
一个形如
YYYYMMDD的字符串,表示第 jj 条记录的完成日期; -
一个长度为 1010 的正整数 pp(数据保证不包含前导零),表示第 jj 条记录的来源学号;
-
两个形如
hh:mm:ss的字符串,分别表示第j条记录的开始时间和结束时间;-
时间范围是 1:00:00 到 24:59:59,且不存在跨天的时间。
-
-
一个精确到小数点后两位的非负浮点数 ll,表示第 jj 条记录的运动距离,单位为千米;
-
一个形如
a'b"的字符串,表示第 jj 条记录的总暂停时间为 aa 分 bb 秒; -
一个非负整数 ss,表示第 jj 条记录的运动总步数。
输出格式
输出文件共包括 nn 行。请你按照学号字典序输出每一位同学的学号、百分制总评成绩以及等级。
每位同学一行,一行内用空格隔开。
样例输入
1 2015011233 M 34 14'30" P 3 3 8 20210508 2015011233 17:02:33 17:19:33 2.99 0'0" 3333 20210509 2015011233 17:12:15 17:38:46 3.01 2'3" 4300 20210510 2015011233 22:03:06 22:13:08 3.05 0'0" 2772 20210511 2015011233 22:08:05 22:28:13 3.02 5'3" 3775 20210512 2015011233 18:03:12 18:17:56 3.02 0'0" 2001 20210513 2015011233 17:30:23 17:46:08 3.01 0'0" 3020 20210513 2015011233 22:03:34 22:20:08 3.04 2'0" 3058 20210514 2015011233 07:16:22 07:32:34 3.00 0'0" 3244
样例输出
2015011233 59 F
数据规模
对于 100\%100% 的数据:
-
n\leq{{4000}}n≤4000
-
0 \leq a,b \leq 590≤a,b≤59
-
0 \leq c \leq 1000≤c≤100
-
m\leq{{1.5\times 10^5}}m≤1.5×105
-
0 \leq l \leq 1000≤l≤100
-
0 \leq s \leq 10^60≤s≤106。
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int m;
struct running{
string ymd;
long long p; //201900130000
string s1; //start
string s2; //end
double l; //km
string ss; //a'b
int s; //bushu
// bool flag;
};
struct student{
long long p; //201900130000
char sex; //M\F
int s; //专项成绩
string ss; //长跑测试成绩 a'b“
char pf; // P/F 体测成绩 10分
int f; //0-5日常表现分数
int c; //到课次数
int score; //最终得分
char grade; //对应等级
vector<running> runv; //日常长跑记录
};
vector<student> vs;
bool cmp1(student st1, student st2){
return st1.p < st2.p;
}
int changpaoscore(string ss, char sex){
string ab = ss;
int a= 0;
int b = 0;
bool flag = false;
int i = 0;
for( i = 0; isdigit(ab[i]); i++)
a = a*10 + ab[i] - '0';
i++;
for( ; isdigit(ab[i]); i++)
b = b*10 + ab[i] - '0';
if(sex == 'M'){ //男
if(a < 12 || (a == 12 && b <=30))
return 20;
if(a < 13 || (a == 13 && b == 0))
return 18;
if(a ==13 && b <= 30)
return 16;
if(a == 13 || ( a==14 && b == 0))
return 14;
if(a == 14 && b <= 30)
return 12;
if(a == 14 || (a==15 && b <= 10))
return 10;
if(a == 15 && b <= 50)
return 8;
if(a == 15 || (a == 16 && b <= 30))
return 6;
if(a == 16 || (a == 17 && b <= 10))
return 4;
if(a < 18 || (a == 18 && b == 0))
return 2;
else return 0;
}
if(sex == 'F'){
if(a < 6 || (a == 6 && b <= 40))
return 20;
if(a == 6 && b <= 57)
return 18;
if(a == 6 || (a == 7 && b <= 14))
return 16;
if(a == 7 && b <= 31)
return 14;
if(a == 7 && b <= 50)
return 12;
if(a == 7 || (a==8 && b <= 5))
return 10;
if(a == 8 && b <= 20)
return 8;
if(a == 8 && b <= 35)
return 6;
if(a == 8 && b <= 50)
return 4;
if(a == 8 || (a == 9 && b == 0))
return 2;
else return 0;
}
}
int pingshichengji(const student& st){
int pingshi = 0;
pingshi += st.f;
int num = 0;
num += st.c;
num += (int)st.runv.size();
if(num >= 18)
pingshi += 5;
if(num >= 15 &&num <= 17)
pingshi += 4;
if(num >= 12 && num <= 14)
pingshi += 3;
if(num >= 9 && num <= 11)
pingshi += 2;
if(num >= 6 && num <= 8)
pingshi += 1;
return pingshi;
}
int timebetween(string s1, string s2){
int time = 0;
int h1 = 0, h2 = 0, m1 = 0, m2 = 0,se1 = 0,se2 = 0;
h1 = (s1[0]-'0') * 10 + s1[1]-'0';
h2 = (s2[0]-'0') * 10 + s2[1] - '0';
time += (h2 - h1) * 3600;
m1 = (s1[3]-'0') * 10 + s1[4]-'0';
m2 = (s2[3]-'0') * 10 + s2[4] - '0';
if(m1 <= m2)
time += 60 * (m2 - m1);
else {
time -= 3600;time += 60 * ( 60 - m1 + m2);
}
se1 = (s1[6]-'0') * 10 + s1[7] - '0';
se2 = (s2[6]-'0') * 10 + s2[7] - '0';
if( se1 <= se2)
time += se2 - se1;
else {
time -= 60;time += (60 - se1 + se2);
}
return time;
}
bool cmp2(running r1,running r2){
int day1 = 0;
int day2 = 0;
for(int i = 4; i <= 7; i++){
day1 += day1 * 10 + r1.ymd[i] - '0';
day2 += day2 * 10 + r2.ymd[i] - '0';
}
if(day1 == day2){
int time = timebetween(r1.s1, r2.s1);
return time > 0;
}
else return day1 < day2;
}
int main() {
// freopen("E:\\untitled\\b.in","r",stdin);
// freopen("E:\\untitled\\final.out","w",stdout);
scanf("%d", &n);
int score = 0;
for (int i = 0; i < n; i++) {
student tempstudent;
cin >> tempstudent.p; //学号
cin >> tempstudent.sex; //性别
cin >> tempstudent.s; //专项成绩
cin >> tempstudent.ss; //长跑测试 a'b”
cin >> tempstudent.pf; //体测是否通过
cin >> tempstudent.f; //日常表现分数
cin >> tempstudent.c; //到课次数
tempstudent.score = 0; //初始化,得分为0
vs.push_back(tempstudent);
}
cin >> m;
for (int i = 0; i < m; i++) {
running temprun;
cin >> temprun.ymd; //YYYYMMDD 完成日期
cin >> temprun.p; //学号
cin >> temprun.s1; //hh:mm:ss开始时间
cin >> temprun.s2; //hh:mm:ss结束时间
cin >> temprun.l; //距离(km)
cin >> temprun.ss; //a'b" 总暂停时间
cin >> temprun.s; //总步数
// temprun.flag = true; //标记该条记录有效
for (int j = 0; j < n; j++) {
if (vs[j].p == temprun.p) {
vs[j].runv.push_back(temprun);
break;
}
}
}
sort(vs.begin(), vs.end(), cmp1); //学号升序排列
for (int i = 0; i < n; i++) {
int score = 0;
score += vs[i].s; //专项成绩
score += changpaoscore(vs[i].ss, vs[i].sex); //长跑测试成绩
if (vs[i].pf == 'P')
score += 10; //体测成绩
sort(vs[i].runv.begin(),vs[i].runv.end(),cmp2);
for (int j = 0; j < vs[i].runv.size();) { //日常长跑记录处理
int valid = 0;
int time = timebetween(vs[i].runv[j].s1, vs[i].runv[j].s2); //日常长跑时间
double speed = vs[i].runv[j].l * 1000.0 / (1.00 * time);
if (speed >= 2 && speed <= 5) {
valid ++;
}
int k = 0;
int a = 0; int b = 0;
string ab = vs[i].runv[j].ss;
for( k = 0; isdigit(ab[k]); k++)
a = a*10 + ab[k] - '0';
k++;
for( ; isdigit(ab[k]); k++)
b = b*10 + ab[k] - '0';
if (a < 4 || (a == 4 && b <= 30)) {
valid ++;
}
double bufu = vs[i].runv[j].l * 1000.0 / vs[i].runv[j].s;
if (bufu <= 1.5) {
valid ++;
}
if (vs[i].sex == 'M' && vs[i].runv[j].l >= 3.00) { //男
valid ++;
}
if (vs[i].sex == 'F' && vs[i].runv[j].l >= 1.50) { //女
valid ++;
}
if(j == 0) valid ++;
else {
int day1 = 0;
int day2 = 0;
for(int tempi = 4; tempi <= 7; tempi++){
day1 = day1 * 10 + vs[i].runv[j].ymd[tempi] - '0';
day2 = day2 * 10 + vs[i].runv[j-1].ymd[tempi] - '0';
}
if(day1 == day2){
int time = timebetween(vs[i].runv[j - 1].s2, vs[i].runv[j].s1);
if(time >= 3600 * 6)
valid ++;
}
else valid++;
}
if(valid == 5)
j ++;
else
vs[i].runv.erase(vs[i].runv.begin() + j);
}
int num1 = (int)vs[i].runv.size();
if (num1 >= 21) score += 10;
if (num1 >= 19 && num1 <= 20) score += 9;
if (num1 >= 17 && num1 <= 18) score += 8;
if (num1 >= 14 && num1 <= 16) score += 7;
if (num1 >= 11 && num1 <= 13) score += 6;
if (num1 >= 7 && num1 <= 10) score += 4;
if (num1 >= 3 && num1 <= 6) score += 2;
if (num1 < 3) score += 0;
score += pingshichengji(vs[i]);
vs[i].score = score;
}
for (int i = 0; i < n; i++) {
cout << vs[i].p << " ";
cout << vs[i].score << " ";
int x = vs[i].score;
if (x >= 95) cout << "A\n";
if (x >= 90 && x < 95) cout << "A-\n";
if (x >= 85 && x < 90) cout << "B+\n";
if (x >= 80 && x < 85) cout << "B\n";
if (x >= 77 && x < 80) cout << "B-\n";
if (x >= 73 && x < 77) cout << "C+\n";
if (x >= 70 && x < 73) cout << "C\n";
if (x >= 67 && x < 70) cout << "C-\n";
if (x >= 63 && x < 67) cout << "D+\n";
if (x >= 60 && x < 63) cout << "D\n";
if (x < 60) cout << "F\n";
}
return 0;
}更多推荐

所有评论(0)