7-16 矩阵A乘以B (15 分)
给定两个矩阵A和B,要求你计算它们的乘积矩阵AB。需要注意的是,只有规模匹配的矩阵才可以相乘。即若A有Ra行、Ca列,B有Rb行、Cb列,则只有Ca与Rb相等时,两个矩阵才能相乘。
输入格式:
输入先后给出两个矩阵A和B。对于每个矩阵,首先在一行中给出其行数R和列数C,随后R行,每行给出C个整数,以1个空格分隔,且行首尾没有多余的空格。输入保证两个矩阵的R和C都是正数,并且所有整数的绝对值不超过100。
输出格式:
若输入的两个矩阵的规模是匹配的,则按照输入的格式输出乘积矩阵AB,否则输出Error: Ca != Rb
,其中Ca
是A的列数,Rb
是B的行数。
输入样例1:
2 3
1 2 3
4 5 6
3 4
7 8 9 0
-1 -2 -3 -4
5 6 7 8
输出样例1:
2 4
20 22 24 16
53 58 63 28
输入样例2:
3 2
38 26
43 -5
0 17
3 2
-11 57
99 68
81 72
输出样例2:
Error: 2 != 3
这个题目简单的矩阵相乘...结果当时打的时候看到了后面的两个题好像写过,结果卡在后面了运行超时了....到最后简单的题目反而没有时间来写了,引以为戒吧,下面是代码:
#include<bits/stdc++.h>
using namespace std;
int a[110][110],b[110][110],temp[110][110];
int main()
{
int ra,ca,rb,cb;
while(~scanf("%d%d",&ra,&ca))
{
for(int i=1;i<=ra;i++)
{
for(int j=1;j<=ca;j++)
{
scanf("%d",&a[i][j]);
}
}
scanf("%d%d",&rb,&cb);
for(int i=1;i<=rb;i++)
{
for(int j=1;j<=cb;j++)
{
scanf("%d",&b[i][j]);
}
}
if(ca!=rb)
{
printf("Error: %d != %d\n",ca,rb);
continue;
}
printf("%d %d\n",ra,cb);
for(int i=1;i<=ra;i++)
{
for(int j=1;j<=cb;j++)
{
int sum=0;
for(int k=1;k<=rb;k++)
{
sum+=a[i][k]*b[k][j];
}
printf("%d",sum);
if(j<=cb-1)
printf(" ");
}
printf("\n");
}
}
return 0;
}
L1-8 猜数字 (20 分)
一群人坐在一起,每人猜一个 100 以内的数,谁的数字最接近大家平均数的一半就赢。本题就要求你找出其中的赢家。
输入格式:
输入在第一行给出一个正整数N(≤104)。随后 N 行,每行给出一个玩家的名字(由不超过8个英文字母组成的字符串)和其猜的正整数(≤ 100)。
输出格式:
在一行中顺序输出:大家平均数的一半(只输出整数部分)、赢家的名字,其间以空格分隔。题目保证赢家是唯一的。
输入样例:
7
Bob 35
Amy 28
James 98
Alice 11
Jack 45
Smith 33
Chris 62
输出样例:
22 Amy
暴力大fa好!!!,世界上没有什么事暴力解决不了的,如果有,那就是因为不够暴力!!!
#include<bits/stdc++.h>
using namespace std;
const int infa=1e9+7;
int main()
{
int n,sum,a[100010],ave,minn,ans;
char ch[11010][110];
while(~scanf("%d",&n))
{
sum=0,minn=infa;
memset(a,0,sizeof(a));
memset(ch,0,sizeof(ch));
for(int i=1;i<=n;i++)
{
scanf("%s%d",ch[i],&a[i]);
}
for(int i=1;i<=n;i++)
{
sum+=a[i];
}
ave=(sum/n)/2;
for(int i=1;i<=n;i++)
{
minn=min(minn,abs(a[i]-ave));
}
for(int i=1;i<=n;i++)
{
if(abs(a[i]-ave)==minn)
{
ans=i;
break;
}
}
printf("%d %s\n",ave,ch[ans]);
}
return 0;
}
L1-1 天梯赛座位分配 (20 分)
天梯赛每年有大量参赛队员,要保证同一所学校的所有队员都不能相邻,分配座位就成为一件比较麻烦的事情。为此我们制定如下策略:假设某赛场有 N 所学校参赛,第 i 所学校有 M[i] 支队伍,每队 10 位参赛选手。令每校选手排成一列纵队,第 i+1 队的选手排在第 i 队选手之后。从第 1 所学校开始,各校的第 1 位队员顺次入座,然后是各校的第 2 位队员…… 以此类推。如果最后只剩下 1 所学校的队伍还没有分配座位,则需要安排他们的队员隔位就坐。本题就要求你编写程序,自动为各校生成队员的座位号,从 1 开始编号。
输入格式:
输入在一行中给出参赛的高校数 N (不超过100的正整数);第二行给出 N 个不超过10的正整数,其中第 i 个数对应第 i 所高校的参赛队伍数,数字间以空格分隔。
输出格式:
从第 1 所高校的第 1 支队伍开始,顺次输出队员的座位号。每队占一行,座位号间以 1 个空格分隔,行首尾不得有多余空格。另外,每所高校的第一行按“#X”输出该校的编号X,从 1 开始。
输入样例:
3
3 4 2
输出样例:
#1
1 4 7 10 13 16 19 22 25 28
31 34 37 40 43 46 49 52 55 58
61 63 65 67 69 71 73 75 77 79
#2
2 5 8 11 14 17 20 23 26 29
32 35 38 41 44 47 50 53 56 59
62 64 66 68 70 72 74 76 78 80
82 84 86 88 90 92 94 96 98 100
#3
3 6 9 12 15 18 21 24 27 30
33 36 39 42 45 48 51 54 57 60
这个题目我觉得是中间七题里面比较难的一道题了,当时看了题目就直接跳过去了,后来想想这样的题目老是不做好像不太好,干脆回来补一下算了...
这个题目我们可以用三维数组来做,f[i][j][k]记载的队员的编号,然后i j k 分别表示的是 i 个学校, j 个队,当前状态下这个队里有k 个人,然后就是一个三重循环来做,记得用一个temp中间变量来存下来上一次是哪个学校的,如果是一个学校的话那么就+2,不是的话相邻就可以了,下面是我的代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
int n,maxx,last,beg,s[maxn],f[maxn][10][10];//s[maxn]记载的是每个学校队里的人数,f[maxn][10][10]记载的是题解里面的状态;
int main()
{
while(~scanf("%d",&n))
{
maxx=0,beg=0;//maxx,beg,分别记载一共要多少次和初始化开始的位置;
for(int i=0;i<n;i++)
{
scanf("%d",&s[i]);
maxx=max(maxx,s[i]);
}
//last记载的是上一个学校
last=-1;
for(int j=0;j<maxx;j++)//第几个队
{
for(int k=0;k<10;k++)//第几个队员
{
for(int i=0;i<n;i++)//第几个学校
{
if(s[i]<=j)
continue;//最开始的几个地方可以去省掉,如果队数比学校数还要多,那就直接跳过;
if(last==i)//如果是一个学校的,那就直接隔一个跳
beg+=2;
else
beg+=1;//否则就隔一个;
f[i][j][k]=beg;//记录这个状态下,队员的编号;
last=i;//更新上一个学校的状态值;
}
}
}
//输出;
for(int i=0;i<n;i++)
{
printf("#%d\n",i);
for(int j=0;j<s[i];j++)
{
for(int k=0;k<10;k++)
{
if(k!=1)
{
printf(" ");
}
printf("%d",f[i][j][k]);
}
printf("\n");
}
}
}
return 0;
}
7-14 整除光棍 (20 分)
这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1、11、111、1111等。传说任何一个光棍都能被一个不以5结尾的奇数整除。比如,111111就可以被13整除。 现在,你的程序要读入一个整数x
,这个整数一定是奇数并且不以5结尾。然后,经过计算,输出两个数字:第一个数字s
,表示x
乘以s
是一个光棍,第二个数字n
是这个光棍的位数。这样的解当然不是唯一的,题目要求你输出最小的解。
提示:一个显然的办法是逐渐增加光棍的位数,直到可以整除x
为止。但难点在于,s
可能是个非常大的数 —— 比如,程序输入31,那么就输出3584229390681和15,因为31乘以3584229390681的结果是111111111111111,一共15个1。
输入格式:
输入在一行中给出一个不以5结尾的正奇数x
(<1000)。
输出格式:
在一行中输出相应的最小的s
和n
,其间以1个空格分隔。
输入样例:
31
输出样例:
3584229390681 15
这个题目我刚开始看了一下准备用高精度写的,后来觉得范围实在太大,而且如果用高精度的话,后面数值的比较还要一位一位的来,所以我觉得很麻烦,所以就没有理他,直接跳到其他题目的,后来看了看别人的想法,发现自己想的太复杂了...(当然是因为菜qwq)
代码如下:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,x,temp,ans,cnt;
while(~scanf("%d",&n))
{
cnt=1;//计算一共有多少位
temp=n;//中间变量存储n,方便下一步的计算;
x=1;//光棍数的小帮手。。。
while(temp/10)
{
temp/=10;
x+=pow(10,cnt);
cnt++;
}
if(n==x)//最开始这种一上来就相等的情况也完全没有考虑到,还是做题做的太少了,考虑的不厚周到
{
printf("1 %d\n",cnt);
continue;
}
x+=pow(10,cnt);//和它自己等位数的不行,试一试下一个,即多一位的那个;
while(x%n)//如果下一位也不行的话
{
printf("%d",x/n);//挨个尝试,题目好像可以保证一定找得到,所以就可以直接穷举,
x=(x%n)*10+1;//相当于是高精度除以低精度的除法运算,但是,这个地方因为是光棍数,注意以前是除下来多了一个0,现在是1;
cnt++;//统计位数
}
printf("%d %d\n",x/n,cnt+1); //输出,注意位数加一
}
return 0;
}
L2-1 分而治之 (25 分)
分而治之,各个击破是兵家常用的策略之一。在战争中,我们希望首先攻下敌方的部分城市,使其剩余的城市变成孤立无援,然后再分头各个击破。为此参谋部提供了若干打击方案。本题就请你编写程序,判断每个方案的可行性。
输入格式:
输入在第一行给出两个正整数 N 和 M(均不超过10 000),分别为敌方城市个数(于是默认城市从 1 到 N 编号)和连接两城市的通路条数。随后 M 行,每行给出一条通路所连接的两个城市的编号,其间以一个空格分隔。在城市信息之后给出参谋部的系列方案,即一个正整数 K (≤ 100)和随后的 K 行方案,每行按以下格式给出:
Np v[1] v[2] ... v[Np]
其中 Np
是该方案中计划攻下的城市数量,后面的系列 v[i]
是计划攻下的城市编号。
输出格式:
对每一套方案,如果可行就输出YES
,否则输出NO
。
输入样例:
10 11
8 7
6 8
4 5
8 4
8 1
1 2
1 4
9 8
9 1
1 10
2 4
5
4 10 3 8 4
6 6 1 7 5 4 9
3 1 8 4
2 2 8
7 9 8 7 6 5 4 2
输出样例:
NO
YES
YES
NO
NO
刚开始的想法,这个题目就是用一个二维数组来存这个图,到最后遍历一遍就可以了,就是再标记一些啥的,最后用标记的结果来判断就可以了,不过做了过后老是爆数据和内存,后来突然发现应该用结构体就可以了(嘤嘤嘤)
不过这个题目只得了23分....不知道哪里被卡住了,不过我感觉我思路超级对的说,,,希望大佬帮我看看哪里的bug
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;
struct a
{
int x,y;//记录两个城市;
}fuck[maxn];
int main()
{
int m,n,ta,tb,k,you,tyou,flag,mark[maxn];
struct a fuck[maxn];
while(~scanf("%d%d",&n,&m))
{
memset(fuck,0,sizeof(fuck));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&ta,&tb);
fuck[i].x=ta;
fuck[i].y=tb;
}
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
flag=1,memset(mark,0,sizeof(mark));//标志变量和标记数组,记得每一次都要初始化,恢复状态;
scanf("%d",&you);
for(int j=1;j<=you;j++)
{
scanf("%d",&tyou);
mark[tyou]=1;//被破了,记为1;
}
for(int i=1;i<=n;i++)//每一条边来遍历
{
if(mark[fuck[i].x]==0&&mark[fuck[i].y]==0)//如果这个边两边都没有破,,证明根本就没有联通,那还打个锤子,那不行,标记,跳了
{
flag=0;
break;
}
}
if(flag==0)
printf("NO\n");
else
printf("YES\n");
}
}
return 0;
}
L2-2 小字辈 (25 分)
本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。
输入格式:
输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。一行中的数字间以空格分隔。
输出格式:
首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。
输入样例:
9
2 6 5 5 -1 5 6 4 7
输出样例:
4
1 9
这个题目看题意的话我首先想到了并查集,不过后来发现使用dfs回溯就可以写出来,这个题我们可以把它看成是一颗树,也就是从树从上到下依次遍历寻找,因为每个节点有可能有多个子代,所以我们可以用vector来进行贮存,我还看见有用优先队列来的,也很好,不过菜鸡的我对于优先队列掌握的不是很好,所以qwq....
上代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
int dep[maxn],beg,temp,k,flag,n;
vector<int> t[maxn];
void dfs(int biao,int depth)//从biao这个节点开始搜,深度为depth;
{
dep[biao]=depth;//记录这个点的深度;
beg=max(beg,depth);//记录最大值也就是最深和最晚辈;
for(int i=0;i<t[biao].size();i++)//这个里面的儿子都来一遍
{
dfs(t[biao][i],depth+1);//看看有没有更深的
}
}
int main()
{
while(~scanf("%d",&n))
{
beg=1,temp=-1,flag=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&k);
t[k].push_back(i);//这个人的儿子入进去;
if(k==-1) //找到老祖宗,也就是最高的点开始往下遍历;
temp=i;
}
dep[temp]=1;//最高一辈,从一开始;
dfs(temp,1);
printf("%d\n",beg);//记录最后的深度并输出;
for(int i=1;i<=n;i++)
{
if(flag==0&&beg==dep[i])//控制空格的输出技巧而已,
{
printf("%d",i);
flag=1;
}
else if(beg==dep[i])//当这个深度对应着是最后的那个深度时,输出。
{
printf(" %d",i);
}
}
printf("\n");
}
return 0;
}
L2-3 名人堂与代金券 (25 分)
对于在中国大学MOOC(http://www.icourse163.org/ )学习“数据结构”课程的学生,想要获得一张合格证书,总评成绩必须达到 60 分及以上,并且有另加福利:总评分在 [G, 100] 区间内者,可以得到 50 元 PAT 代金券;在 [60, G) 区间内者,可以得到 20 元PAT代金券。全国考点通用,一年有效。同时任课老师还会把总评成绩前 K 名的学生列入课程“名人堂”。本题就请你编写程序,帮助老师列出名人堂的学生,并统计一共发出了面值多少元的 PAT 代金券。
输入格式:
输入在第一行给出 3 个整数,分别是 N(不超过 10 000 的正整数,为学生总数)、G(在 (60,100) 区间内的整数,为题面中描述的代金券等级分界线)、K(不超过 100 且不超过 N 的正整数,为进入名人堂的最低名次)。接下来 N 行,每行给出一位学生的账号(长度不超过15位、不带空格的字符串)和总评成绩(区间 [0, 100] 内的整数),其间以空格分隔。题目保证没有重复的账号。
输出格式:
首先在一行中输出发出的 PAT 代金券的总面值。然后按总评成绩非升序输出进入名人堂的学生的名次、账号和成绩,其间以 1 个空格分隔。需要注意的是:成绩相同的学生享有并列的排名,排名并列时,按账号的字母序升序输出。
输入样例:
10 80 5
cy@zju.edu.cn 78
cy@pat-edu.com 87
1001@qq.com 65
uh-oh@163.com 96
test@126.com 39
anyone@qq.com 87
zoe@mit.edu 80
jack@ucla.edu 88
bob@cmu.edu 80
ken@163.com 70
输出样例:
360
1 uh-oh@163.com 96
2 jack@ucla.edu 88
3 anyone@qq.com 87
3 cy@pat-edu.com 87
5 bob@cmu.edu 80
5 zoe@mit.edu 80
因为时间有点晚,这个题的代码就不上了,简单说一下思路,输入了过后注意利用STL库里面的sort函数,在最后加上一个
bool cmp(struct a ta,struct a tb)
{
if(ta.score==tb.score)
{
return ta.s<tb.s;
}
else if(ta.score!=tb.score)
return ta.score>tb.score;
}
这样的东西加入sort函数帮忙排序就行了,
唯一注意的时最后的输出有坑,有并列的,处理一下就好了,这里引用了我看到的比较好的写法
a[0].id = 1;
for(int i = 1;i < n;i ++)
{
if(a[i].df == a[i - 1].df) a[i].id = a[i - 1].id;//如果分数相等,就把id都相等
else a[i].id = i+1;//否则+1;
}
cout << ans << endl;
for(int i = 0; a[i].id <=k;i ++)//循环的中间部分,看最后的id到了没有,
{
if(i >= n) return 0;//比总数还多当然不行
else
cout << a[i].id << " " << a[i].zh << " " << a[i].df << endl;//其它情况直接输出
}
补题就到这里了(菜鸡还是需要努力啊,补题的时候看了好多大佬的题解,真的超级棒啊!)加油!