目录
L1-002 打印沙漏
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
输入格式:
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输出格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
PS:上下层分而虑之,可事半而功倍矣!
#include<stdio.h>
#include<math.h>
int main (){
int x,n,i,j;
char c;
scanf("%d %c",&n,&c);
x=sqrt((n+1)/2);
for(i=0;i<x;i++){
for(j=0;j<i;j++)
printf(" ");
for(j=0;j<2*(x-i)-1;j++)
printf("%c",c);
printf("\n");
}
for(i=2;i<=x;i++){
for(j=0;j<x-i;j++)
printf(" ");
for(j=0;j<2*i-1;j++)
printf("%c",c);
printf("\n");
}
printf("%d", n-2*x*x+1);
return 0;
}
L1-003 个位数统计
给定一个 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
的升序输出。
PS:颇多细节尤需注意。
#include<stdio.h>
int main()
{
char n[1000];
scanf("%s",n);
int i,sum=0,j=0,array[10] = {0};
while(n[j] != '\0')
{
array[n[j] - '0']++;
j++;
sum++;
}
for ( i = 0; i < 10; i++)
{
if (array[i] != 0)
{
printf("%d:%d\n",i,array[i]);
}
}
return 0;
}
L1-006 连续因子
一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。
输入格式:
输入在一行中给出一个正整数 N(1<N<231)。
输出格式:
首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1*因子2*……*因子k
的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。
PS:连续因子,百思不得其解!
#include<stdio.h>
#include<math.h>
int main (){
int i,j,n;
int num=0,sum=0,t=0,longqi=0,qi=0;
scanf("%d",&n);
int x=sqrt(n);
for(i=2;i<=x;i++){
num=0;
sum=n;
qi=i;
for(j=i;sum!=0&&sum%j==0;j++){
sum/=j;
num++;
}
if(num>t){
t=num;
longqi=qi;
}
}
if(t==0)printf("1\n%d",n);
else{
printf("%d\n",t);
for(i=longqi;i<longqi+t;i++){
if(i!=longqi)printf("*");
printf("%d",i);
}
}
return 0;
}
L1-009 N个数求和
本题的要求很简单,就是求N
个数字的和。麻烦的是,这些数字是以有理数分子/分母
的形式给出的,你输出的和也必须是有理数的形式。
输入格式:
输入第一行给出一个正整数N
(≤100)。随后一行按格式a1/b1 a2/b2 ...
给出N
个有理数。题目保证所有分子和分母都在长整型范围内。另外,负数的符号一定出现在分子前面。
输出格式:
输出上述数字和的最简形式 —— 即将结果写成整数部分 分数部分
,其中分数部分写成分子/分母
,要求分子小于分母,且它们没有公因子。如果结果的整数部分为0,则只输出分数部分。
PS:分母通分(求公约数和公倍数),情况复杂,是本题难点,
#include <stdio.h>
long long gcd(long long a,long long b)//求最大公约数。
{
if(a == 0)
return 0;
else
return (b == 0) ? a : gcd(b, a % b);
}
int main()
{
int N;
long long lcp;//用以记录最小公倍数
long long a,b,c,d;
int i = 1;
scanf("%d",&N);
scanf("%lld/%lld",&a,&b);
int t0 = gcd(a,b);
if(a)
{
a /= t0;
b /= t0;
}
while(i < N)
{
scanf("%lld/%lld",&c,&d);
lcp = b / gcd(b,d) * d;//通过最大公约数换算出两个分母的最小公倍数
a = a * lcp / b + c * lcp / d;//通分后分子和
b = lcp;
int t0 = gcd(a,b);
if(t0 != 0)//从扩大最小公倍数之后的形式变换回来
{
a = a / t0;
b = b / t0;
}
i++;
}
if(a && a/b == 0)/// 整数部分为0 且 a不为 0
printf("%lld/%lld\n",a%b,b);
else if(a%b == 0)/// 小数部分为0
printf("%lld\n",a/b);
else
printf("%lld %lld/%lld\n",a/b,a%b,b);
return 0;
}
L1-025 正整数A+B
题的目标很简单,就是求两个正整数A
和B
的和,其中A
和B
都在区间[1,1000]。稍微有点麻烦的是,输入并不保证是两个正整数。
输入格式:
输入在一行给出A
和B
,其间以空格分开。问题是A
和B
不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。
注意:我们把输入中出现的第1个空格认为是A
和B
的分隔。题目保证至少存在一个空格,并且B
不是一个空字符串。
输出格式:
如果输入的确是两个正整数,则按格式A + B = 和
输出。如果某个输入不合要求,则在相应位置输出?
,显然此时和也是?
。
PS:倒序循环,正确表示,值得揣摩!
#include<stdio.h>
#include<string.h>
int main()
{
char a[1000], b[1000];
scanf("%s", &a);
gets(b);
int x = 0, y = 0, tempa = 1, tempb = 1;
int sumx = 1,sumy=1;
for (int i = strlen(a)-1;i >=0;i--)//这里到0结束,可以与下面的循环做对比
{
if (a[i] - '0' >= 0 && a[i] - '0' <= 9)//这里使用倒序循环是有道理的,因为下面的sumx便于运算
{
x += (a[i] - '0') * sumx;
sumx *= 10;
if (a[0] == '0' || x > 1000)//这里我们都可以写出来,大家可以和下面的if做对比会发现是不一样的
tempa = 0;
}
else
{
tempa = 0;
}
}
for (int j = strlen(b)-1;j >=1;j--)//这里是需要到1结束的,因为b[0]是空格
{
if (b[j] - '0'>=0 && b[j] - '0' <= 9)
{
y += (b[j] - '0') * sumy;
sumy *= 10;
if (b[1] == '0' || y > 1000)//承接上面的循环条件,这里需要判断b[0]
tempb = 0;
}
else
{
tempb = 0;
}
}
if (tempa&&tempb)//最后的输出也是比较容易出错的,我们的tempa和tempb一定要写在前面,否则会报错的,可以试一试就看出来问题了,我在这里徘徊了很久
printf("%d + %d = %d", x,y,x+y);
else if (tempa)
printf("%d + ? = ?", x);
else if (tempb)
printf("? + %d = ?", y);
else
printf("? + ? = ?");
return 0;
}
L1-027 出租
一时间网上一片求救声,急问这个怎么破。其实这段代码很简单,index
数组就是arr
数组的下标,index[0]=2
对应 arr[2]=1
,index[1]=0
对应 arr[0]=8
,index[2]=3
对应 arr[3]=0
,以此类推…… 很容易得到电话号码是18013820100
。
本题要求你编写一个程序,为任何一个电话号码生成这段代码 —— 事实上,只要生成最前面两行就可以了,后面内容是不变的。
输入格式:
输入在一行中给出一个由11位数字组成的手机号码。
输出格式:
为输入的号码生成代码的前两行,其中arr
中的数字必须按递减顺序给出。
PS:多个数组储存不同信息,条理清晰很重要!
#include <stdio.h>
int main()
{
char tell[12];
scanf("%s",tell);
int arr[10];
int index[12];
int a[10]={0}; //判断是否读入过此数字
for(int i=0;i<11;i++) a[tell[i]-'0']=1;
int num_=0; //记录有多少个数字
for(int i=9;i>=0;i--) if(a[i]) arr[num_++]= i; //降序生成arr
for(int i=0;i<11;i++)
{
int n=tell[i]-'0';
int k; //记录数字
for(k=0;k<10;k++)
{
if(n==arr[k]) break; //找到在arr中的保存位置
}
index[i]=k;
}
printf("int[] arr = new int[]{");
printf("%d",arr[0]);
for(int i=1;i<num_;i++)
printf(",%d",arr[i]);
printf("};\n");
printf("int[] index = new int[]{");
printf("%d",index[0]);
for(int i=1;i<11;i++)
printf(",%d",index[i]);
printf("};\n");
return 0;
}
L1-030 一帮一
“一帮一学习小组”是中小学中常见的学习组织方式,老师把学习成绩靠前的学生跟学习成绩靠后的学生排在一组。本题就请你编写程序帮助老师自动完成这个分配工作,即在得到全班学生的排名后,在当前尚未分组的学生中,将名次最靠前的学生与名次最靠后的异性学生分为一组。
输入格式:
输入第一行给出正偶数N
(≤50),即全班学生的人数。此后N
行,按照名次从高到低的顺序给出每个学生的性别(0代表女生,1代表男生)和姓名(不超过8个英文字母的非空字符串),其间以1个空格分隔。这里保证本班男女比例是1:1,并且没有并列名次。
输出格式:
每行输出一组两个学生的姓名,其间以1个空格分隔。名次高的学生在前,名次低的学生在后。小组的输出顺序按照前面学生的名次从高到低排列。
PS:以flag来显示是否配对是关键!
#include<stdio.h>
struct student {
char name[20];
int sex;
}s[50];
int main()
{
int N, flag[50] = { 0 }, i, j, k;
scanf("%d", &N);
for (i = 0; i < N; i++)
{
scanf("%d %s", &s[i].sex, s[i].name);
}
for (i = 0; i < N; i++)
{
for (j = N - 1; j >= 0; j--)
{
if (flag[i] == 0 && flag[j] == 0 && s[i].sex != s[j].sex)
{
printf("%s %s\n", s[i].name, s[j].name);
flag[i] = 1;
flag[j] = 1;
}
}
}
return 0;
}
L1-033 出生年
以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才遇到4个数字都不相同的年份。”也就是说,直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求,自动填充“我出生于y
年,直到x
岁才遇到n
个数字都不相同的年份”这句话。
输入格式:
输入在一行中给出出生年份y
和目标年份中不同数字的个数n
,其中y
在[1, 3000]之间,n
可以是2、或3、或4。注意不足4位的年份要在前面补零,例如公元1年被认为是0001年,有2个不同的数字0和1。
输出格式:
根据输入,输出x
和能达到要求的年份。数字间以1个空格分隔,行首尾不得有多余空格。年份要按4位输出。注意:所谓“n
个数字都不相同”是指不同的数字正好是n
个。如“2013”被视为满足“4位数字都不同”的条件,但不被视为满足2位或3位数字不同的条件。
PS:找位数和注意循环条件是关键!
#include<stdio.h>
int main(void)
{
int n,f,m,c1,c2,c3,c4,t,count;
scanf("%04d %d",&n,&m);
f=n; //保留最初的年份,因为后面的循环会依次增加年份
while(1){
t=n;
c1=t/1000; //找出千位数 如1988中的1
t=t%1000;
c2=t/100; //找出百位数 如1988中的9
t=t%100;
c3=t/10; //找出十位数 如1988中的8
c4=t%10; //找出个位数 如1988中的8
count=1;
if(c1!=c2&&c1!=c3&&c1!=c4){
//这条语句是在判断,c1是不是和c2,c3,c4都不相等,是的话就有两个不一样啦
count++;
}
if(c2!=c3&&c2!=c4){
//此句在判断c2是否和c3,c4相等,若都不相等就有三个不一样了
count++;
}
if(c3!=c4){
//此句在判断c3和c4是否相等,若不相等,则有四个不一样。
count++;
}
if(count==m) break;
n++;
//将n++放在后面,而不是前面是因为 初始的n也是要进入循环的。不然测试案例2,会报错啦~
}
printf("%d %04d",n-f,n);
return 0;
}
L1-034 点赞
微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。本题就要求你写个程序,通过统计一个人点赞的纪录,分析这个人的特性。
输入格式:
输入在第一行给出一个正整数N(≤1000),是该用户点赞的博文数量。随后N行,每行给出一篇被其点赞的博文的特性描述,格式为“K F1⋯FK”,其中1≤K≤10,Fi(i=1,⋯,K)是特性标签的编号,我们将所有特性标签从1到1000编号。数字间以空格分隔。
输出格式:
统计所有被点赞的博文中最常出现的那个特性标签,在一行中输出它的编号和出现次数,数字间隔1个空格。如果有并列,则输出编号最大的那个。
PS:本题不难,唯一需要斟酌的是如何记录编号的次数。以下提供了一个针对编号范围不大,通过开数组一一对应的方法。
#include<stdio.h>
int main()
{
int m[1000]={0},a,b,c,d,e=999,N,n;
scanf("%d",&N);
for(a=0;a<N;a++)
{
scanf("%d",&n);
for(b=0;b<n;b++)
{
scanf("%d",&c);
m[c-1]++;
}
}
for(d=999;d>0;d--)
if(m[e]<m[d-1])
e=d-1;
printf("%d %d",e+1,m[e]);
return 0;
}
L1-039 古风排版
中国的古人写文字,是从右向左竖向排版的。本题就请你编写程序,把一段文字按古风排版。
输入格式:
输入在第一行给出一个正整数N(<100),是每一列的字符数。第二行给出一个长度不超过1000的非空字符串,以回车结束。
输出格式:
按古风格式排版给定的字符串,每列N个字符(除了最后一列可能不足N个)。
输入样例:
4
This is a test case
输出样例:
asa T
st ih
e tsi
ce s
解题思路:用二维数组依次存储字符串的字符,当字符数的到n时,列数加一,输出时横纵坐标互换,逆置输出。
#include<stdio.h>
#include<string.h>
int main(){
char a[101][101],ch;
int i,j,n,h,l;
scanf("%d",&n);//n为每列的字符数
getchar();
h=0;l=0;//h为行,l为列
while((ch=getchar())!='\n'){
h+=l/n;//当一列满n时行数的字符数加一
l%=n;//每列的字符数从一到n循环
a[h][l++]=ch;//将字符存储到二维数组中
}
//逆置输出字符
for(i=0;i<n;i++){ //控制二维数组的行数
for(j=h;j>=0;j--){//控制二维数组每行的字符数
putchar(a[j][i]?a[j][i]:' ');
}
putchar('\n');
}
}
L1-043 阅览室
天梯图书阅览室请你编写一个简单的图书借阅统计程序。当读者借书时,管理员输入书号并按下S
键,程序开始计时;当读者还书时,管理员输入书号并按下E
键,程序结束计时。书号为不超过1000的正整数。当管理员将0作为书号输入时,表示一天工作结束,你的程序应输出当天的读者借书次数和平均阅读时间。
注意:由于线路偶尔会有故障,可能出现不完整的纪录,即只有S
没有E
,或者只有E
没有S
的纪录,系统应能自动忽略这种无效纪录。另外,题目保证书号是书的唯一标识,同一本书在任何时间区间内只可能被一位读者借阅。
输入格式:
输入在第一行给出一个正整数N(≤10),随后给出N天的纪录。每天的纪录由若干次借阅操作组成,每次操作占一行,格式为:
书号
([1, 1000]内的整数) 键值
(S
或E
) 发生时间
(hh:mm
,其中hh
是[0,23]内的整数,mm
是[0, 59]内整数)
每一天的纪录保证按时间递增的顺序给出。
输出格式:
对每天的纪录,在一行中输出当天的读者借书次数和平均阅读时间(以分钟为单位的精确到个位的整数时间)。
思路:
先把题目读懂。简化为:虽有许多读者去借书,但无关紧要,完全可以看作只有一个读者去借书;应该注意,题目只要求输出当天的读者借书次数和平均阅读时间,即这一天一共有几本书被借出去,一天的借书时长加起来除以借出去书的个数。不是一本书的阅读时长(平均阅读时间要注意转化为整形),还要注意的是每天都是崭新的一天,所以一天工作结束后,所有数据全部清零。
1.输入天数,按天数进行while循环
2.定义一个整型数组time和book,分别存放每天每本书的借书时长和借还书次数,这些数据初始化每天开始之时都是0,因为每天都是崭新的一天。
3.一天中,按要求输入书号,按键,小时,分钟。当书号为0时,一天工作结束,跳出本循环。书号不为0时,对这本书的借书加还书的次数做统计,按键为S时,记录每本书借书时间,按键为E并且这本书有记录被借出时,计算这本书本次的借书时长,之后再加到一天中总的借书时长sumtime中,在还书时要用count计算借书次数。
4.输出,当count 等于0时,也就是每天的借书总数为0,输出“0 0”。否则就输出借书次数和平均阅读时长,平均阅读时长要四舍五入转化为整型。
5.最后一天工作结束之后所有数据全部清零。
#include<iostream>
using namespace std;
int main()
{
//本题还要计算天数,一天工作结束,你的程序应输出当天的读者借书次数和平均阅读时间。
int n,count = 0,num;//n为天数,count 为一天中借书次数,num为书名号
char a;//按键S ,E
int h,m;//小时分钟
int sumtime = 0;//一天所有书籍总阅读时长
cin>>n;
while (n--)
{
int time[1001] = {0};//每本书的借书时长
int book[1001] = {0};//每本书的借书次数
while (scanf("%d %c %d:%d",&num,&a,&h,&m))
{
if (num == 0)
{
break;
}
book[num]++;//计数,用来标记S,E是不是成双成对的出现的
if (a == 'S')
{
time[num] = h*60+m; //cout<<time[num]<<endl;
}
else if (book[num]%2==0 && a == 'E')//S,E成对的出现才进行借书时长的计算
{
count++;
time[num] = h*60 + m - time[num];
sumtime +=time[num];
time[num] = 0;
}
}
if (count == 0) cout<<"0 0"<<endl;
else cout<<count<<" "<<(int)(1.0*sumtime/count + 0.5)<<endl;//四舍五入
count = 0;
sumtime = 0;//一天结束后全清零
}
return 0;
}
L1-046 整除光棍
这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由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个空格分隔。
妙解:模拟列式除法,即——当不是整除时,我们在光棍数后面加1,新的被除数正好是前一个余数乘十加一,前面的商不变——故而我们可以每次输出一个商,并且每次的被除数用前一个余数乘十加一表示,这样就避免了出现存不下的数的情况。
#include<stdio.h>
int main(){
int n, r = 1, w = 1;//r表示1,11,111类型的数据,w记录位数
scanf("%d", &n);
while(r < n){
r *= 10;
r++;
w++;
}
while(1){
printf("%d", r/n);//输出商
r %= n;//取余
if(r ==0 )//取余后,若等于0,则证明能被整除,break掉
break;
r = r * 10 + 1;//不等于0则在余数后一位加上1
w++;
}
printf(" %d",w);
return 0;
}
L1-048 矩阵A乘以B
给定两个矩阵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
PS:矩阵相乘如何用代码实现至关重要!
#include<stdio.h>
int main(){
int ra,ca,rb,cb;
//给 A 数组赋值
scanf("%d%d",&ra,&ca);
int a[ra][ca];
for(int i=0;i<ra;i++){
for(int j=0;j<ca;j++){
scanf("%d",&a[i][j]);
}
}
// 给B数组赋值
scanf("%d%d",&rb,&cb);
int b[rb][cb];
for(int i=0;i<rb;i++){
for(int j=0;j<cb;j++){
scanf("%d",&b[i][j]);
}
}
//判断是否满足输出求乘积条件
if(ca!=rb){
printf("Error: %d != %d",ca,rb);
return 0;
}
int c[ra][cb];
for(int i=0;i<ra;i++){
int sum=0;
for(int j=0;j<cb;j++){
int sum=0;
for(int k=0;k<ca;k++){
sum+=(a[i][k]*b[k][j]);
}
c[i][j]=sum;
}
}
//打印输出
printf("%d %d\n",ra,cb);
for(int i=0;i<ra;i++){
for(int j=0;j<cb;j++){
printf("%d",c[i][j]);
if(j!=cb-1){
printf(" ");
}
}
if(i!=ra-1){
printf("\n");
}
}
return 0;
}
L1-049 天梯赛座位分配
天梯赛每年有大量参赛队员,要保证同一所学校的所有队员都不能相邻,分配座位就成为一件比较麻烦的事情。为此我们制定如下策略:假设某赛场有 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
PS:看似简单,实则水深需多思。
#include<bits/stdc++.h>
using namespace std;
int main()
{
// freopen("data.txt","r",stdin);
int n,i,j,a[101],b[110][1001],t=0,max=0,f=-1;//f是标识符,用于表明是否同校
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
if(max<a[i])
max=a[i];
}
for(j=0;j<max*10;j++)
for(i=0;i<n;i++)
{
if(j<a[i]*10)
{
if(i!=f)
{
t++;
b[i][j]=t;
f=i;
}
else
{
t+=2;
b[i][j]=t;
f=i;
}
}
}
for(i=0;i<n;i++)
{
cout<<"#"<<i+1<<endl;
for(t=0;t<a[i]*10;t++)
{
cout<<b[i][t];
if((t+1)%10==0)
cout<<endl;
else
cout<<" ";
}
}
}
L1-050 倒数第N个字符串
给定一个完全由小写英文字母组成的字符串等差递增序列,该序列中的每个字符串的长度固定为 L,从 L 个 a 开始,以 1 为步长递增。例如当 L 为 3 时,序列为 { aaa, aab, aac, ..., aaz, aba, abb, ..., abz, ..., zzz }。这个序列的倒数第27个字符串就是 zyz。对于任意给定的 L,本题要求你给出对应序列倒数第 N 个字符串。
输入格式:
输入在一行中给出两个正整数 L(2 ≤ L ≤ 6)和 N(≤105)。
输出格式:
在一行中输出对应序列倒数第 N 个字符串。题目保证这个字符串是存在的。
输入样例:
3 7417
输出样例:
pat
PS:以输入”3 1“为例,应输出”zzz“,故有”num-=1“。
#include<stdio.h>
#include<string.h>
int a[10010];
int main(){
int l,num;
scanf("%d %d",&l,&num);
int t,k=1;
num-=1;
//序号变成进制 zzz为0 zzy为1....zza为25,逢26进1
//可以类比10进制 0 1 2...9 逢10进一
while(num){
t=num%26;
num/=26;
a[k++]='z'-t;
}
//上面的举例:如果l=3,num=27,经过num-=1,num=26,t=26%26=0;
//个位啥也没有,num/=26,num=1,第二位进一
//输出
for(int i=l;i>0;i--){
if(!a[i])printf("z");
else printf("%c",a[i]);
}
// puts("");
}
L1-054 福到了
“福”字倒着贴,寓意“福到”。不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出。这里要处理的每个汉字是由一个 N × N 的网格组成的,网格中的元素或者为字符 @
或者为空格。而倒过来的汉字所用的字符由裁判指定。
输入格式:
输入在第一行中给出倒过来的汉字所用的字符、以及网格的规模 N (不超过100的正整数),其间以 1 个空格分隔;随后 N 行,每行给出 N 个字符,或者为 @
或者为空格。
输出格式:
输出倒置的网格,如样例所示。但是,如果这个字正过来倒过去是一样的,就先输出bu yong dao le
,然后再用输入指定的字符将其输出。
输入样例 1:
$ 9
@ @@@@@
@@@ @@@
@ @ @
@@@ @@@
@@@ @@@@@
@@@ @ @ @
@@@ @@@@@
@ @ @ @
@ @@@@@
输出样例 1:
$$$$$ $
$ $ $ $
$$$$$ $$$
$ $ $ $$$
$$$$$ $$$
$$$ $$$
$ $ $
$$$ $$$
$$$$$ $
PS:其实不难,核心无非是s[i][j]!=s[n-i-1][n-j-1],注意getchar吞回车。
#include<stdio.h>
char s[105][105];
int main()
{
char c;
int n;
scanf("%c %d",&c,&n);
getchar(); //吞换行回车
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
scanf("%c",&s[i][j]);
}
getchar(); //吞换行回车
}
int flag=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(s[i][j]!=s[n-i-1][n-j-1]) //对称
{
flag=1;
}
}
}
if(!flag)
{
printf("bu yong dao le\n");
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(s[n-i-1][n-j-1] != ' ')
{
printf("%c",c);
}
else
{
printf(" ");
}
}
printf("\n");
}
return 0;
}
L1-058 6翻了
“666”是一种网络用语,大概是表示某人很厉害、我们很佩服的意思。最近又衍生出另一个数字“9”,意思是“6翻了”,实在太厉害的意思。如果你以为这就是厉害的最高境界,那就错啦 —— 目前的最高境界是数字“27”,因为这是 3 个 “9”!
本题就请你编写程序,将那些过时的、只会用一连串“6666……6”表达仰慕的句子,翻译成最新的高级表达。
输入格式:
输入在一行中给出一句话,即一个非空字符串,由不超过 1000 个英文字母、数字和空格组成,以回车结束。
输出格式:
从左到右扫描输入的句子:如果句子中有超过 3 个连续的 6,则将这串连续的 6 替换成 9;但如果有超过 9 个连续的 6,则将这串连续的 6 替换成 27。其他内容不受影响,原样输出。
输入样例:
it is so 666 really 6666 what else can I say 6666666666
输出样例:
it is so 666 really 9 what else can I say 27
PS:不必用 9 以及 27 去替换那些 6;只需遇到 6 开始计数,直到遍历到非 6 的元素结束,判断 6 的个数,按要求打印即可;
#include<stdio.h>
#include<string.h>
int main()
{
char str[1005];
int count = 0, i, j;
gets(str);
for (i = 0; i <= strlen(str); i++)
{
if (str[i] == '6')
{
count++;
}
else
{
if (count > 9)
printf("27");
else if (count > 3)
printf("9");
else
{
for (j = 0; j < count; j++)
{
printf("6");
}
}
printf("%c", str[i]);
count = 0;
}
}
return 0;
}
L1-078 吉老师的回归
曾经在天梯赛大杀四方的吉老师决定回归天梯赛赛场啦!
为了简化题目,我们不妨假设天梯赛的每道题目可以用一个不超过 500 的、只包括可打印符号的字符串描述出来,如:Problem A: Print "Hello world!"
。
众所周知,吉老师的竞赛水平非常高超,你可以认为他每道题目都会做(事实上也是……)。因此,吉老师会按照顺序看题并做题。但吉老师水平太高了,所以签到题他就懒得做了(浪费时间),具体来说,假如题目的字符串里有 qiandao
或者 easy
(区分大小写)的话,吉老师看完题目就会跳过这道题目不做。
现在给定这次天梯赛总共有几道题目以及吉老师已经做完了几道题目,请你告诉大家吉老师现在正在做哪个题,或者吉老师已经把所有他打算做的题目做完了。
提醒:天梯赛有分数升级的规则,如果不做签到题可能导致团队总分不足以升级,一般的选手请千万不要学习吉老师的酷炫行为!
输入格式:
输入第一行是两个正整数 N,M (1≤M≤N≤30),表示本次天梯赛有 N 道题目,吉老师现在做完了 M 道。
接下来 N 行,每行是一个符合题目描述的字符串,表示天梯赛的题目内容。吉老师会按照给出的顺序看题——第一行就是吉老师看的第一道题,第二行就是第二道,以此类推。
输出格式:
在一行中输出吉老师当前正在做的题目对应的题面(即做完了 M 道题目后,吉老师正在做哪个题)。如果吉老师已经把所有他打算做的题目做完了,输出一行 Wo AK le
。
输入样例 1:
5 1
L1-1 is a qiandao problem.
L1-2 is so...easy.
L1-3 is Easy.
L1-4 is qianDao.
Wow, such L1-5, so easy.
输出样例 1:
L1-4 is qianDao.
PS:getchar不能少!!!注意cnt与m的关系!!!
/*
#include<stdio.h>
#include<string.h>
int main(){
int m,n,i,j,cnt=0;
char s[501],q[8]="qiandao",e[5]="easy";
scanf("%d %d",&n,&m);
getchar();//神来之笔!!很关键!!!
while(n--){
char *p1,*p2;
gets(s);
p1=strstr(s,q);
p2=strstr(s,e);
if(p1||p2) continue;
else cnt++;
if(cnt>m) {puts(s);break;}
}
if(cnt<=m) printf("Wo AK le");
return 0;
}
以上全对。
*/
#include<stdio.h>
#include<string.h>
int main(){
int m,n,i,j,cnt=0;
char s[501],q[8]="qiandao",e[5]="easy";
scanf("%d %d",&n,&m);
getchar();//神来之笔!!很关键!!!
while(n--){
char *p1,*p2;
gets(s);
p1=strstr(s,q);
p2=strstr(s,e);
if(p1||p2) continue;
else cnt++;
if(cnt==m) {gets(s);puts(s);break;}
}
if(cnt<m) printf("Wo AK le");
return 0;
}//改变了if判断条件,第三个测试点过不去
L1-080 乘法口诀数列
本题要求你从任意给定的两个 1 位数字 a1 和 a2 开始,用乘法口诀生成一个数列 {an},规则为从 a1 开始顺次进行,每次将当前数字与后面一个数字相乘,将结果贴在数列末尾。如果结果不是 1 位数,则其每一位都应成为数列的一项。
输入格式:
输入在一行中给出 3 个整数,依次为 a1、a2 和 n,满足 0≤a1,a2≤9,0<n≤103。
输出格式:
在一行中输出数列的前 n 项。数字间以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
2 3 10
输出样例:
2 3 6 1 8 6 8 4 8 4
PS:注意逻辑条件和循环体内语句块设计!!
#include<stdio.h>
int main(){
int a1,a2,n,i=2,j;
scanf("%d %d %d",&a1,&a2,&n);
int s[1001]={0};
s[0]=a1,s[1]=a2;
for(i=2,j=2;i<n;i++,j++){
int t=s[j-2]*s[j-1];//为什么t=s[i-2]*s[i-1]就不行???
if(t<=9)
s[i]=t;
else{
s[i]=t/10;
s[++i]=t%10;
}
}
for(i=0;i<n;i++){
printf("%d",s[i]);
if(i!=n-1)
printf(" ");
}
return 0;
}