学位证
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
众所周知,在山东理工大学拿到学位证是需要一定的学分绩点的,但是由于程序设计的日益重要,学校决定让某些程序设计成绩十分优秀但是总学分绩点不够的同学也拿到学位证。
现在已知拿到学位证所需的学分绩点 x 和程序设计的优秀分数线 y 和 n 个同学的成绩信息。
你能写一个程序输出可以拿到学位证的同学的姓名和学号么?
Input
第一行一个数字n,代表同学总数 (n<=1000)。
第二行开始 n 行每行分别输入第 i 个同学的学分绩点,程序设计成绩,姓名和学号,用空格分隔,学分绩点和程序设计成绩均在int范围内,姓名和学号为不超过11位的字符串。
最后输入拿到学位证所需的绩点 x 和程序设计优秀线 y ( 1<=x , y <=1e9 )。
Output
按照输入顺序输出能拿到学位证的同学的姓名和学号。
合格的定义为总学分绩点合格或程序设计成绩优秀。
Sample Input
3 50 50 goudan 18272727272 61 40 zhangsan 18110505050 50 80 lisi 1817272aaaa 60 70
Sample Output
zhangsan 18110505050 lisi 1817272aaaa
Hint
题目所述规定纯属虚构,拿学位证还是要看绩点的。
Source
行走的二叉树
这个题目为签到题,判断所给的数据是否大于最后所给出的优秀绩点的数据,只要有一项大于优秀绩点的数据就可以输出其姓名学号,运用结构体即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int a;
int b;
char q[110];
char w[110];
}s[1100];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d %d %s %s",&s[i].a,&s[i].b,s[i].q,s[i].w);
}
int x,y;
scanf("%d %d",&x,&y);
for(int i=0;i<n;i++)
{
if(s[i].a>=x||s[i].b>=y)
{
printf("%s %s\n",s[i].q,s[i].w);
}
}
return 0;
}
猜数游戏
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
Alice 和 Bob 正在玩一个猜数游戏,游戏规则如下。
有且仅有一个未知的整数需要Alice去猜测,Bob事先已经知道了这个数。
在游戏中 Bob 总共提供给 Alice n 条线索,而Alice只有一次猜测机会。
每条线索由 L 和 R 两个整数组成,表示要猜测的数大于等于L,并且小于等于R。
Alice是足够聪明的,不过她希望你能告诉她,一次猜对的概率是多少。
(数据保证Bob给Alice提供的线索均是正确的)
Input
第一行输入一个正整数 T 表示数据的组数。(1 <= T <= 100)
每组开始输入一个正整数 n。(1 <= n <= 100)
接下来 n 行,每行输入两个整数 L 和 R。 (-100 <= L <= R <= 100)
Output
输出共T行,第 i 行表示第 i 组测试数据的答案。
答案用分数的形式(A/B)进行表示,注意不要输出多余的空格。
Sample Input
3 1 -100 100 2 3 4 4 5 2 3 6 4 7
Sample Output
1/201 1/1 1/3
Hint
Source
lxw
这个题目就是计算出所给出的所有判断区间的交集,即取最小的区间进行求区间长度,代码实现起来并不是特别难,就是运用一下最大最小函数进行判断一下最终的最小区间,可以设置两个变量,l,r,l来记录数据左端点的最大值,r来记录右端点的最小值,这样既可求出所有区间的交集。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int max(int x,int y)
{
if(x>y)
{
return x;
}
else
{
return y;
}
}
int min(int x,int y)
{
if(x<y)
{
return x;
}
else
{
return y;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t>0)
{
int n;
scanf("%d",&n);
int l,r;
l=-100;
r=100;
while(n>0)
{
int x,y;
scanf("%d %d",&x,&y);
l=max(l,x);
r=min(r,y);
n--;
}
int res=0;
res=r-l+1;
printf("1/%d\n",res);
t--;
}
return 0;
}
easy math problem
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
对于一个数n,有以下两种操作:
一是减一,需要花费 a 。
但是如果 n 能被 k 整除,还可以花费 b 让 n 除以 k。
请问将这个数变为1最少要多少花费?
Input
第一行一个整数n(n<=1e5)
第二行三个正整数分别为a, b, k ( 0 < a , b , k <= n ,n*a<1e9 ).
Output
输出一个整数代表最小花费。
Sample Input
10 1 2 2
Sample Output
6
Hint
Source
行走的二叉树
此题就是简单贪心问题,选择最优路径进行解题,当 n不能被 k 整除时只能减一并花费 a,当 n 能被 k 整除时判断一下整除花费的 b和使 用减一操作达到相同效果时花费的大小,使用花费小的操作即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
int a,b,k;
scanf("%d %d %d",&a,&b,&k);
int ans=0;
while(n!=1)
{
if(n%k==0&&b<(n-n/k)*a)
{
ans=ans+b;
n=n/k;
}
else
{
ans=ans+a;
n=n-1;
}
}
printf("%d\n",ans);
return 0;
}
排队买饭
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
理工大的食堂到了饭点人可以说是相当多了,按理来说排队的时候先来的同学应该会先走,但实际情况可能并不一样,我们注意到对于一个队列往往由以下两种操作组成
当输入 1 时:代表队列最左面的同学完成了买饭操作,由于他会帮他的好朋友一起买,所以买完饭后会叫上所有与他编号相同的好朋友一起走,如果输入1时队伍已经为空则不删除。换句话说,如果序列不为空则会在序列中删除最左边的一个元素和与之编号相同的所有元素,否则不删除。
当输入 2 时:代表编号为 b 的同学想要插队买饭,由于他与编号为 a 的同学是好朋友,他会插入到队列从左往右的第一个编号为 a 的同学右边,如果队伍中没有编号为 a 的同学,他就会伤心的离开。换句话说,会在队列的从左往右的第一个 a 后面插入一个 b,如果队列中没有 a 则不插入。
需要注意的是,每次操作后都需要你判断一下队列是否为空,如果为空则输出“EMPTY”。
最后一行输出所有操作后的序列。
Input
第一行一个数 n 代表初始时序列中的元素 ( n<=1e5)
第二行 n个 int 范围内的数,最多有1000个不同的。
第三行一个数 m 代表操作的次数。(m<=1e5)
后面m行每行第一个数代表操作种类。
如果操作为 2 则再输入两个数 a,b。
Output
对于每次操作,如果操作后队列为空,则输出"EMPTY"。
所有操作完成后输出最终的序列。
(最下方提示有补充测试样例)
Sample Input
6 1 1 4 3 1 2 3 2 4 5 1 1
Sample Output
5 3 2
Hint
补充样例:
input:
6
1 1 4 3 1 2
5
2 6 5
1
1
1
1
output:
EMPTY
Source
行走的二叉树
链表的建立删除插入问题,这个题目有点难度,将插入删除结合在了一起,在代码实现方面有一点困难,大家在真正的考试中可以适当选择放弃。对链表的插入删除等操作比较熟悉的大佬们这个题应该不在话下,就是代码实现方面比较复杂,在考试中是比较考验手速与熟练度的一道题。
AC代码:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct node
{
int data;
node *next;
};
int main()
{
//freopen("data2.in","r",stdin);
//freopen("data2.out","w",stdout);
int n;
cin>>n;
node *head,*tail,*p;
head=new(node);
head->next=NULL;
tail=head;
for(int i=0; i<n; i++)//尾插法建表
{
p=new(node);
cin>>p->data;
p->next=tail->next;
tail->next=p;
tail=p;
}
int m;
cin>>m;
node *q;
int op;
while(m--)
{
cin>>op;
if(op==1)//删除
{
p=head;
q=head->next;
int d;
if(q)
d=q->data;
while(q)
{
if(q->data==d)
{
p->next=q->next;
q=q->next;
}
else
{
p=p->next;
q=q->next;
}
}
}
else//插入
{
p=head->next;
int aa,bb;
cin>>aa>>bb;
while(p)
{
if(p->data==aa)
{
q=new(node);
q->data=bb;
q->next=p->next;
p->next=q;
p=p->next;
break;
}
p=p->next;
}
}
if(head->next==NULL)//判空
{
cout<<"EMPTY"<<endl;
}
}
p=head->next;
int f=0;
while(p)//输出
{
if(!f)
{
cout<<p->data;
f=1;
}
else
{
cout<<" "<<p->data;
}
p=p->next;
}
cout<<endl;
return 0;
}
本人的能力有限,在考试中也仅仅做出来了这4道题目,下面的题目都是为大佬准备的题目,我考虑了好几天才明白一些,将大佬们的代码放上,大家如果有想钻研或者是“真*大佬”的同学可以参考一下。以下的题目就不讲解了,过于复杂我自己也不太懂。
射箭游戏
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
Alice正在玩一个射箭游戏。
现在Alice有 N 枝不同的箭,每只箭有它的攻击力。
有 M 个怪物,每个怪物有它的生命值,击杀怪物后会掉落金币。
每只箭最多使用一次,每个怪物最多被攻击一次。
且为了“简单”起见,怪物掉落金币数等于其生命值。
问Alice最多可以获得多少金币。
Input
输入数据共三行。
第一行有两个正整数N和M,分别表示箭的数量和怪物的数量。(1 <= N <= 1000000, 1 <= M <= 1000000)
第二行有N个正整数,第 i 个数表示第 i 枝箭的攻击力 。(1 <= 攻击力 <= 1000000000)
第三行有M个正整数,第 i 个数表示第 i 个怪物的生命值和掉落金币数 。 (1 <= 生命值 <= 1000000000)
友情提示:答案会超出int范围,请使用长整形 long long(%lld) 进行计算。
Output
输出一个整数,表示Alice最多可以获得多少金币。
Sample Input
5 5 1 4 5 7 9 2 10 8 6 4
Sample Output
20
Hint
Source
lxw
AC代码:
#include <stdio.h>
int atk[1123456],hp[1123456];
void sort(int s[],int l,int r) { //从大到小快速排序
int i,j,key;
if(l>=r) return;
i = l;j = r;key=s[i];
while(i<j) {
while(s[j]<=key&&j>i)j--;
s[i] = s[j];
while(s[i]>=key&&i<j)i++;
s[j] = s[i];
}
s[i] = key;
sort(s,l,i-1);
sort(s,i+1,r);
}
int main() {
int n, m, i;
scanf("%d%d",&n,&m);
for(i = 1; i <= n; i++) scanf("%d",&atk[i]);
for(i = 1; i <= m; i++) scanf("%d",&hp[i]);
sort(atk, 1, n); //弓箭攻击力从大到小排序
sort(hp, 1, m); //怪物生命值从大到小排序
int now = 1; /w记录当前第一个未击杀怪物编号
long long ans = 0; //记录获得的金币
for(int i = 1; i <= n; i++) { //待使用的弓箭为 i
while(atk[i]<hp[now]&&now<=m) now++; //向后找到第一个可以射死的怪物
if(now>m) break; //假如已经无法找到,那么就退出
ans += hp[now]; //假如找到了,那么就使用第i枝弓箭攻击,击杀第now个怪物,并获得其金币
now++; //当前怪物已被击杀,所以now后移到下一个。
}
printf("%lld",ans);
return 0;
}
小D的棋盘
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
小D有一个神奇的棋盘,棋盘有n行,m列。这个棋盘为什么神奇呢?因为这个棋盘被施加了一个魔法,小D每念一次咒语,棋盘上的棋子就能分裂到相邻的上下左右四个格子上,分裂之后原来的会消失,如果他的某个方向上没有格子(比如第一行没有向上的格子),那么他就不会向上分裂。现在小D想知道他念了k次咒语之后棋盘上现在会有多少个棋子。注意:每个格子能够放无数个棋子,分裂后的棋子再念一次咒语棋子能继续分裂。
Input
输入n,m。(2<=n<=20,2<=m<=20)表示棋盘的行列。
接下来n行,每行m个数字aij(0<=aij<=1),每个数字代表这个格子初始的时候有几个棋子。
接下来一行输入k(1<=k<=10)。
Output
输出一个数字表示小D念了k次咒语之后棋盘上现在会有多少个棋子。这个数字保证在int的范围内。
Sample Input
3 3 0 0 0 0 1 0 0 0 0 2
Sample Output
12
Hint
在示例中,念了一次咒语后棋盘的情况是:
0 1 0
1 0 1
0 1 0
再念一次后棋盘的情况是:
2 0 2
0 4 0
2 0 2
最终棋盘有12个棋子。
Source
cat_of_orange
AC代码:
#include <stdio.h>
int dp[2][20][20];
int main()
{
int n,m,q;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
scanf("%d",&dp[0][i][j]);
}
scanf("%d",&q);
for(int t=1;t<=q;t++)
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
dp[t%2][i][j]=0;
if(i)dp[t%2][i][j]+=dp[t%2^1][i-1][j];
if(j)dp[t%2][i][j]+=dp[t%2^1][i][j-1];
if(i<n-1)dp[t%2][i][j]+=dp[t%2^1][i+1][j];
if(j<m-1)dp[t%2][i][j]+=dp[t%2^1][i][j+1];
}
}
int ans=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
ans+=dp[q%2][i][j];
printf("%d\n",ans);
return 0;
}
}
小D的一串数字
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
小D在纸上随便写了两串数字,“23333333”,“0123456789”。第一个串中含有7个重复的相邻的数字,第二个串中不含相邻的重复的数字。小D喜欢第一类串,但是他放低了要求,只要一串数字中含有超过两个重复的相邻的数字,小D就喜欢这串数字。现在他想知道,长度为n的的所有数字串,最多有多少个串会被他喜欢?但是小D是个数学白痴,麻烦你帮他解决这个问题。
Input
输入一个N,(3=<N<=10),代表数字串的长度。
Output
输出一个整数,表示小D最多喜欢多少串。
Sample Input
3
Sample Output
10
Hint
样例中111,222,333,444,555,666,777,888,999,000,这10个串是被小D喜欢的。
Source
cat_of_orange
AC代码:
#include <stdio.h>
int dp[50][50];
int main()
{
int n;
for(int i=0;i<10;i++)
dp[1][i]=1;
scanf("%d",&n);
for(int i=2;i<=n;i++)
for(int j=0;j<10;j++){
for(int k=0;k<10;k++)
if(j!=k)dp[i][j]+=dp[i-1][k]+dp[i-1][k+10];
dp[i][j+10]=dp[i-1][j];
dp[i][j+20]=dp[i-1][j+10]+dp[i-1][j+20]*10;
}
int ans=0;
for(int i=0;i<10;i++)
ans+=dp[n][i+20];
printf("%d\n",ans);
}