7-1 重要的话说三遍
这道超级简单的题目没有任何输入。
你只需要把这句很重要的话 —— “I'm gonna WIN!”——连续输出三遍就可以了。
注意每遍占一行,除了每行的回车不能有任何多余字符。
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
for(int i=1;i<=3;++i)
printf("I'm gonna WIN!\n");
return 0;
}
7-2 日期格式化
世界上不同国家有不同的写日期的习惯。比如美国人习惯写成“月-日-年”,而中国人习惯写成“年-月-日”。下面请你写个程序,自动把读入的美国格式的日期改写成中国习惯的日期。
输入格式:
输入在一行中按照“mm-dd-yyyy”的格式给出月、日、年。题目保证给出的日期是1900年元旦至今合法的日期。
输出格式:
在一行中按照“yyyy-mm-dd”的格式给出年、月、日。
输入样例:
03-15-2017
输出样例:
2017-03-15
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
思路:
读入一行,由于形式固定,直接找到对应位置输出。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
string a;
cin>>a;
for(int i=6;i<=9;++i) printf("%c",a[i]);
printf("-");
for(int i=0;i<=1;++i) printf("%c",a[i]);
printf("-%c%c",a[3],a[4]);
return 0;
}
//01-34-6789
7-3 大笨钟
微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。不过由于笨钟自己作息也不是很规律,所以敲钟并不定时。一般敲钟的点数是根据敲钟时间而定的,如果正好在某个整点敲,那么“当”数就等于那个整点数;如果过了整点,就敲下一个整点数。另外,虽然一天有24小时,钟却是只在后半天敲1~12下。例如在23:00敲钟,就是“当当当当当当当当当当当”,而到了23:01就会是“当当当当当当当当当当当当”。在午夜00:00到中午12:00期间(端点时间包括在内),笨钟是不敲的。
下面就请你写个程序,根据当前时间替大笨钟敲钟。
输入格式:
输入第一行按照hh:mm
的格式给出当前时间。其中hh
是小时,在00到23之间;mm
是分钟,在00到59之间。
输出格式:
根据当前时间替大笨钟敲钟,即在一行中输出相应数量个Dang
。如果不是敲钟期,则输出:
Only hh:mm. Too early to Dang.
其中hh:mm
是输入的时间。
输入样例1:
19:05
输出样例1:
DangDangDangDangDangDangDangDang
输入样例2:
07:05
输出样例2:
Only 07:05. Too early to Dang.
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
思路:
当小于或正好等于12点时,则不是敲钟期。其他时间取整循环输出。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int hh,mm;
scanf("%d:%d",&hh,&mm);
if(hh-12<0||hh==12&&mm==0)
printf("Only %02d:%02d. Too early to Dang.\n",hh,mm);
else
{
for(int i=1;i<=hh-12;++i)
{
printf("Dang");
}
if(mm>0) printf("Dang");
}
return 0;
}
7-4 拯救外星人
你的外星人朋友不认得地球上的加减乘除符号,但是会算阶乘 —— 正整数 N 的阶乘记为 “N!”,是从 1 到 N 的连乘积。所以当他不知道“5+7”等于多少时,如果你告诉他等于“12!”,他就写出了“479001600”这个答案。
本题就请你写程序模仿外星人的行为。
输入格式:
输入在一行中给出两个正整数 A 和 B。
输出格式:
在一行中输出 (A+B) 的阶乘。题目保证 (A+B) 的值小于 12。
输入样例:
3 6
输出样例:
362880
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
思路:
计算(a+b)!。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int main()
{
int a,b;
scanf("%d%d",&a,&b);
ll ans=1;
for(int i=1;i<=a+b;++i)
ans*=i;
printf("%lld",ans);
return 0;
}
7-5 个位数统计
给定一个 k 位整数 N=dk−110k−1+⋯+d1101+d0 (0≤di≤9, i=0,⋯,k−1, dk−1>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。
输入格式:
每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。
输出格式:
对 N 中每一种不同的个位数字,以 D:M
的格式在一行中输出该位数字 D
及其在 N 中出现的次数 M
。要求按 D
的升序输出。
输入样例:
100311
输出样例:
0:2
1:3
3:1
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
思路:
哈希统计数字出现次数,从小到大输出时跳过个数为0的数字。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int a[20];
int main()
{
string s;
cin>>s;
for(int i=0;i<s.length();++i)
a[s[i]-'0']++;
for(int i=0;i<=9;++i)
if(a[i]==0) continue;
else printf("%d:%d\n",i,a[i]);
return 0;
}
7-6 正整数A+B
题的目标很简单,就是求两个正整数A
和B
的和,其中A
和B
都在区间[1,1000]。稍微有点麻烦的是,输入并不保证是两个正整数。
输入格式:
输入在一行给出A
和B
,其间以空格分开。问题是A
和B
不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。
注意:我们把输入中出现的第1个空格认为是A
和B
的分隔。题目保证至少存在一个空格,并且B
不是一个空字符串。
输出格式:
如果输入的确是两个正整数,则按格式A + B = 和
输出。如果某个输入不合要求,则在相应位置输出?
,显然此时和也是?
。
输入样例1:
123 456
输出样例1:
123 + 456 = 579
输入样例2:
22. 18
输出样例2:
? + 18 = ?
输入样例3:
-100 blabla bla...33
输出样例3:
? + ? = ?
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
思路:
基础思路:判断两个串是不是只有数字,是则计算输出,不是则 ' ? ' 输出。
注意事项:
1.以第一个空格分开,也就是说b中可能含有空格,故不能用scanf或cin读入b。
2.a、b的范围是[1,1000],超出区间的为 ' ? ' 。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int main()
{
char s1[1100],s2[1100];
int a=0,b=0,f1=0,f2=0,aa=0,bb=0;
scanf("%s",s1);
cin.getline(s2,1100);
if(s2==" ") f1=f2=1;
for(int i=0;i<strlen(s1);++i)
{
if(s1[i]<='9'&&s1[i]>='0')
{
a=a*10+(s1[i]-'0');
if(a>1000) {f1=1;break;}
if(i==strlen(s1)-1) aa=1;
}
else {f1=1;break;}
}
for(int i=1;i<strlen(s2);++i)
{
if(s2[i]<='9'&&s2[i]>='0')
{
b=b*10+(s2[i]-'0');
if(b>1000) {f2=1;break;}
if(i==strlen(s2)-1) bb=1;
}
else {f2=1;break;}
}
if(!f1&&aa&&a==0) f1=1;
if(!f2&&bb&&b==0) f2=1;
if(f1) printf("?");
else printf("%d",a);
printf(" + ");
if(f2) printf("?");
else printf("%d",b);
printf(" = ");
if(f1||f2) printf("?\n");
else printf("%d\n",a+b);
return 0;
}
7-7 打印沙漏
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
思路:
先输出一个倒三角,再输出下方的正三角。
假设 k 行倒三角所需的符号数为 n ,易得:n=k*k;
所以整个图形 k+(k-1) 行共有 n=2*k*k-1 个符号。
根据输入的 n 倒推出最大的整数 k 值,由此打印两个三角。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int main()
{
int n;char c;scanf("%d %c",&n,&c);
//倒三角要k行,k*k-1<=n;
int k=sqrt((n+1)/2.0);
for(int i=1;i<=k;++i)
{
for(int j=1;j<=i-1;++j) printf(" ");
for(int j=1;j<=(k-i)*2+1;++j) printf("%c",c);
printf("\n");
}
for(int i=2;i<=k;i++)
{
for(int j=1;j<=k-i;++j) printf(" ");
for(int j=1;j<=i*2-1;++j) printf("%c",c);
printf("\n");
}
int num=n-(k*k*2-1);
printf("%d",num);
return 0;
}
7-8 机工士姆斯塔迪奥
在 MMORPG《最终幻想14》的副本“乐欲之所瓯博讷修道院”里,BOSS 机工士姆斯塔迪奥将会接受玩家的挑战。
你需要处理这个副本其中的一个机制:N×M 大小的地图被拆分为了 N×M 个 1×1 的格子,BOSS 会选择若干行或/及若干列释放技能,玩家不能站在释放技能的方格上,否则就会被击中而失败。
给定 BOSS 所有释放技能的行或列信息,请你计算出最后有多少个格子是安全的。
输入格式:
输入第一行是三个整数 N,M,Q (1≤N×M≤105,0≤Q≤1000),表示地图为 N 行 M 列大小以及选择的行/列数量。
接下来 Q 行,每行两个数 Ti,Ci,其中 Ti=0 表示 BOSS 选择的是一整行,Ti=1 表示选择的是一整列,Ci 为选择的行号/列号。行和列的编号均从 1 开始。
输出格式:
输出一个数,表示安全格子的数量。
输入样例:
5 5 3
0 2
0 4
1 3
输出样例:
12
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
思路:
最初 n 行,m 列,如果少了a行、b列,那结果为(n-a)*(m-b)。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int a[100100],b[100100];
int main()
{
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=q;++i)
{
int t,c;
scanf("%d%d",&t,&c);
if(t==0&&a[c]==0)//行
{
a[c]=1;--n;
}
if(t==1&&b[c]==0)
{
b[c]=1;--m;
}
}
ll ans=m*n;
if(ans<0) ans=0;
printf("%lld",ans);
return 0;
}
7-9 排座位
布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。
输入格式:
输入第一行给出3个正整数:N
(≤100),即前来参宴的宾客总人数,则这些人从1到N
编号;M
为已知两两宾客之间的关系数;K
为查询的条数。随后M
行,每行给出一对宾客之间的关系,格式为:宾客1 宾客2 关系
,其中关系
为1表示是朋友,-1表示是死对头。注意两个人不可能既是朋友又是敌人。最后K
行,每行给出一对需要查询的宾客编号。
这里假设朋友的朋友也是朋友。但敌人的敌人并不一定就是朋友,朋友的敌人也不一定是敌人。只有单纯直接的敌对关系才是绝对不能同席的。
输出格式:
对每个查询输出一行结果:如果两位宾客之间是朋友,且没有敌对关系,则输出No problem
;如果他们之间并不是朋友,但也不敌对,则输出OK
;如果他们之间有敌对,然而也有共同的朋友,则输出OK but...
;如果他们之间只有敌对关系,则输出No way
。
输入样例:
7 8 4
5 6 1
2 7 -1
1 3 1
3 4 1
6 7 -1
1 2 1
1 4 1
2 3 -1
3 4
5 7
2 3
7 2
输出样例:
No problem
OK
OK but...
No way
代码长度限制 16 KB
时间限制 200 ms
内存限制 64 MB
思路:
四种情况,是朋友,输出“
No problem
”不是朋友,没共同朋友,也不是敌人,输出“
OK
”是敌人但有共同朋友,输出“
OK but...
”是敌人,没有共同朋友,输出“
No way
”。除了有无共同朋友,其他都可以直观得到。而共同朋友可以使用并查集解决。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int a[110][110];
int f[110];//i的好朋友源头
int szfind(int x)
{
if(f[x]==x) return x;
return f[x]=szfind(f[x]);
}
void szunion(int x,int y)
{
f[y]=x;
}
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;++i) f[i]=i;
for(int i=1;i<=m;++i)
{
int p,q,v;scanf("%d%d%d",&p,&q,&v);
a[p][q]=a[q][p]=v;
if(v==1)
{
int r1=szfind(p),r2=szfind(q);
if(r1!=r2) szunion(r1,r2);
}
}
for(int i=1;i<=k;++i)
{
int p,q;scanf("%d%d",&p,&q);
if(a[p][q]==1) printf("No problem\n");
else if(a[p][q]==0) printf("OK\n");
else if(a[p][q]==-1&&szfind(p)==szfind(q)) printf("OK but...\n");
else printf("No way\n");
}
return 0;
}
7-10 名人堂与代金券
对于在中国大学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
代码长度限制 16 KB
时间限制 250 ms
内存限制 64 MB
思路:
总面值符合要求的相加即可得出。
用sort加结构体排序,输出时额外处理排名相同的人即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
struct node
{
char nam[20];
int sc;
}a[10010];
ll sum;
bool cmp(node a,node b)
{
if(a.sc==b.sc)
{
int ret=strcmp(a.nam,b.nam);
if(ret<=0) return 1;
else return 0;
}
return a.sc>b.sc;
}
int main()
{
int n,g,k;
scanf("%d%d%d",&n,&g,&k);
for(int i=1;i<=n;++i)
{
scanf("%s%d",a[i].nam,&a[i].sc);
if(a[i].sc>=60)
{
if(a[i].sc>=g) sum+=50;
else sum+=20;
}
}
sort(a+1,a+n+1,cmp);
printf("%lld\n",sum);
int num=1,tot=1;
while(k>=tot&&tot<=n)
{
while(a[num].sc==a[tot].sc)
{
printf("%d %s %d\n",num,a[tot].nam,a[tot].sc);
++tot;
}
num=tot;
}
return 0;
}
7-11 包装机
一种自动包装机的结构如图 1 所示。首先机器中有 N 条轨道,放置了一些物品。轨道下面有一个筐。当某条轨道的按钮被按下时,活塞向左推动,将轨道尽头的一件物品推落筐中。当 0 号按钮被按下时,机械手将抓取筐顶部的一件物品,放到流水线上。图 2 显示了顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态。
图1 自动包装机的结构
图 2 顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态
一种特殊情况是,因为筐的容量是有限的,当筐已经满了,但仍然有某条轨道的按钮被按下时,系统应强制启动 0 号键,先从筐里抓出一件物品,再将对应轨道的物品推落。此外,如果轨道已经空了,再按对应的按钮不会发生任何事;同样的,如果筐是空的,按 0 号按钮也不会发生任何事。
现给定一系列按钮操作,请你依次列出流水线上的物品。
输入格式:
输入第一行给出 3 个正整数 N(≤100)、M(≤1000)和 Smax(≤100),分别为轨道的条数(于是轨道从 1 到 N 编号)、每条轨道初始放置的物品数量、以及筐的最大容量。随后 N 行,每行给出 M 个英文大写字母,表示每条轨道的初始物品摆放。
最后一行给出一系列数字,顺序对应被按下的按钮编号,直到 −1 标志输入结束,这个数字不要处理。数字间以空格分隔。题目保证至少会取出一件物品放在流水线上。
输出格式:
在一行中顺序输出流水线上的物品,不得有任何空格。
输入样例:
3 4 4
GPLT
PATA
OMSA
3 2 3 0 1 2 0 2 2 0 -1
输出样例:
MATA
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
思路:
模拟整个过程。
用tot[]记录轨道要推的,stack q表示栈,按要求处理。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
char a[110][1010];
int tot[1010];//初始位置 0,表示该推这个了
stack<char> q;
int main()
{
int n,m,s;
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=n;++i)
scanf("%s",a[i]);
int k;
while(scanf("%d",&k),k!=-1)
{
if(k==0)
{
if(q.size()>0)
{
printf("%c",q.top());
q.pop();
}
}
else
{
if(tot[k]>=m)
{
continue;
}
if(q.size()==s)
{
printf("%c",q.top());
q.pop();
}
q.push(a[k][tot[k]]);
tot[k]++;
}
}
return 0;
}
7-12 愿天下有情人都是失散多年的兄妹
呵呵。大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人、父母、祖父母、曾祖父母、高祖父母)则不可通婚。本题就请你帮助一对有情人判断一下,他们究竟是否可以成婚?
输入格式:
输入第一行给出一个正整数N
(2 ≤ N
≤104),随后N
行,每行按以下格式给出一个人的信息:
本人ID 性别 父亲ID 母亲ID
其中ID
是5位数字,每人不同;性别M
代表男性、F
代表女性。如果某人的父亲或母亲已经不可考,则相应的ID
位置上标记为-1
。
接下来给出一个正整数K
,随后K
行,每行给出一对有情人的ID
,其间以空格分隔。
注意:题目保证两个人是同辈,每人只有一个性别,并且血缘关系网中没有乱伦或隔辈成婚的情况。
输出格式:
对每一对有情人,判断他们的关系是否可以通婚:如果两人是同性,输出Never Mind
;如果是异性并且关系出了五服,输出Yes
;如果异性关系未出五服,输出No
。
输入样例:
24
00001 M 01111 -1
00002 F 02222 03333
00003 M 02222 03333
00004 F 04444 03333
00005 M 04444 05555
00006 F 04444 05555
00007 F 06666 07777
00008 M 06666 07777
00009 M 00001 00002
00010 M 00003 00006
00011 F 00005 00007
00012 F 00008 08888
00013 F 00009 00011
00014 M 00010 09999
00015 M 00010 09999
00016 M 10000 00012
00017 F -1 00012
00018 F 11000 00013
00019 F 11100 00018
00020 F 00015 11110
00021 M 11100 00020
00022 M 00016 -1
00023 M 10012 00017
00024 M 00022 10013
9
00021 00024
00019 00024
00011 00012
00022 00018
00001 00004
00013 00016
00017 00015
00019 00021
00010 00011
输出样例:
Never Mind
Yes
Never Mind
No
Yes
No
Yes
No
No
鸣谢用户 徐校波 修正数据!
代码长度限制 16 KB
时间限制 200 ms
内存限制 64 MB
思路:
父母的父母这种情况很容易想到深搜来遍历。判断a,b是否在五服内,只需在遍历 a 时将 a 五服内的人全部标记,遍历 b 时遇到有标记的就表明a,b在五服内有亲缘。
询问时,可能会问到父母,注意要将父母的性别记录下来。
代码:
#include<bits/stdc++.h>
using namespace std;
int re[100100][5];//re[i][1]存父亲,re[i][2]存母亲
int sex[100100];//性别
int vis[100100];//五服之内是否出现
int f=0;
void dfs(int a,int dep)
{
if(dep>=5) return;
for(int i=1;i<=2;++i)
{
if(re[a][i]==-1||re[a][i]==0) continue;
if(!vis[re[a][i]])
{
vis[re[a][i]]=1;
dfs(re[a][i],dep+1);
}
else//b与a有重叠
{
f=1;return;
}
}
}
int main()
{
int n;scanf("%d",&n);
for(int i=1;i<=n;++i)
{
int id;
scanf("%d ",&id);
scanf("%c %d%d",&sex[id],&re[id][1],&re[id][2]);
if(re[id][1]!=-1) sex[re[id][1]]='M';
if(re[id][2]!=-1) sex[re[id][2]]='F';//可能询问父母的关系
}
int k;scanf("%d",&k);
for(int i=1;i<=k;++i)
{
int a,b;scanf("%d%d",&a,&b);
if(sex[a]==sex[b])
{
printf("Never Mind\n");
continue;
}
memset(vis,0,sizeof(vis));
vis[a]=vis[b]=1;
f=0;
dfs(a,1);
dfs(b,1);//如果不重叠,那么b不会遍历到a的五服
if(f==1) printf("No\n");
else printf("Yes\n");
}
return 0;
}