1 Big Dream
边长为a(a>1)的正方形,其边上的总星数可以平均分配给四条边,每条边分到a-1个星,共s=4*(a-1)颗星
反推可得s/4+1=a。
#include<stdio.h>
#include<string.h>
int main()
{
int b,i,a,j,k;
k=0;
while(scanf("%d",&a),a)
{
if(k)
printf("\n");
if(a<=3)printf("1\n*\n");//当1颗星组成正方形
else
{
b=a/4+1;
printf("%d\n",b);
for(i=1;i<=b;++i)
{
printf("*"); //输出每行第一列*
for(j=2;j<b;++j)//判断第一行及最后一行全部是* ,其余为空格
{
if(i==1||i==b)printf("*");
else
{
printf(" ");
}
}
printf("*\n");//输出每行最后一列*
}
}
k=1;
}
return 0;
}
2 Base64编码简单版
先将原字符串转化为二进制码8位一组存入数组,再每6位解出一个对应数,对应到base64的字符串中。
#include<stdio.h>
int main()
{
char c[2000],d[500]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
int i,j,l,x[10000],a,s;
gets(c);
l=strlen(c);
for(i=1;i<=l;++i)
{
a=128;//2^(8-1)
for(j=1;j<=8;++j)//8位一组存入数组
{
x[8*(i-1)+j-1]=c[i-1]/a;
c[i-1]%=a;
a/=2;
}
}
for(i=1;i<=l*8/6;++i)
{
s=0;
a=32;
for(j=1;j<=6;++j)//6位一组读出
{
s+=x[6*(i-1)+j-1]*a;
a/=2;
}
printf("%c",d[s]);
}
printf("\n");
return 0;
}
3 千年幻想乡 ~ History of the Moon
题目较长。提取信息得到两种纪年法可解释为
三系统:a:0 1 2 0 1 2 0 1 2……
b:0 1 2 3 0 1 2 3 0 1 2 3……
c:0 1 2 3 4 0 1 2 3 4……
年份 s:1 2 3 4 5 6 7 8 9 10……
历经60年会重新回到abc同时为0的情况 不难发现a=(s-1)%3;b=(s-1)%4;c=(s-1)%5
同理
二系统:d:0 1 2 3 4 5 6 7 8 9 0 1……
e:0 1 2 3 4 5 6 7 8 9 10 11 0 1……
s:1 2 3 4 5 6 7 8 9 10 11 12 13……
历经60年会重新回到de同时为0的情况 不难发现d=(s-1)%10;e=(s-1)%12;
据题意,循环从 日与春与土 和 乙酉 开始一一对应
#include<stdio.h>
#include<string.h>
int main()
{
int n,d,s,i,j;
char san[3][10],er[2][10];
char xitong[3][10]={"hi","tsuki","hoshi"};
char siji[4][10]={"haru","natsu","aki","fuyu"};//注意定义的顺序乙酉与日与春与土是字符串的开始
char shuxing[5][10]={"tsuchi","ka","mizu","ki","kin"};
char tian[10][10]={"yi","bing","ding","wu","ji","geng","xin","ren","gui","jia"};
char di[12][10]={"you","xu","hai","zi","chou","yin","mao","chen","si","wu","wei","shen"};
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%d",&d);
if(d==1)
{
s=0;
scanf("%s%s%s",san[0],san[1],san[2]);
while(1)
{
s++;
if(strcmp(xitong[(s-1)%3],san[0])==0&&strcmp(siji[(s-1)%4],san[1])==0&&strcmp(shuxing[(s-1)%5],san[2])==0)break;//当循环到与题目给的相同时退出得到年份
}
printf("%s %s\n",tian[(s-1)%10],di[(s-1)%12]);
}
else
{
scanf("%s%s",er[0],er[1]);
s=0;
while(1)
{
s++;
if(strcmp(tian[(s-1)%10],er[0])==0&&strcmp(di[(s-1)%12],er[1])==0)break;
}
printf("%s %s %s\n",xitong[(s-1)%3],siji[(s-1)%4],shuxing[(s-1)%5]);
}
}
return 0;
}
4 求出前m大的数
运用桶排序避免超时 此方法应用于数据较小的排序。
#include<stdio.h>
int main()
{
int a,b,i,j,max,maxshu,d,g,k,n,o;
int x[4000],s;
while(scanf("%d%d",&a,&b)!=EOF)
{
int q[10000]={0};
k=0;n=0;max=0;
for(i=1;i<=a;++i)//读入数据
{
scanf("%d",&x[i-1]);
}
for(i=1;i<a;++i)//存入相加的数据
{
for(j=i+1;j<=a;++j)
{
s=x[i-1]+x[j-1];
q[s]++;//同一个数的数目
if(n==0||s>max)
max=s;
n++;
}
}
printf("%d",max);
b--;
q[max]--;
do//从最大依次往下找 直到输出题目要求的数目
{
for(i=1;i<=q[max];++i)
{
printf(" %d",max);
b--;
if(b==0)break;
}
if(b==0)break;
}while(max--);
printf("\n");
}
return 0;
}
5 童年生活二三事
在台阶数n大于3后,可以将跳的情况分为两种:
a 先跳一阶由0到1,之后从1跳到第n阶的可能性等同于 从0跳到n-1的可能性
b 先跳两阶由0到2,之后从2跳到第n阶的可能性等同于 从0跳到n-2的可能性
即s[n]=s[n-1]+s[n-2] 斐波那契数列
#include<stdio.h>
int main()
{
int a,i,j;
int x[1000];
while(scanf("%d",&a),a)
{
x[1]=1;x[2]=2;
if(a==1||a==2)printf("%d\n",x[a]);
else
{
for(i=3;i<=a;++i)
{
x[i]=x[i-1]+x[i-2];
}
printf("%d\n",x[a]);
}
}
return 0;
}
6 隐藏的最大整数
字符串转化为数。
#include<stdio.h>
#include<string.h>
int main()
{
char c[2000];
int x;
int i,j,l,t,d,p,s,max;
gets(c);
l=strlen(c);
p=1;//记录这是出现的第一个数
for(i=0;i<l;++i)
{
x=0;
if(c[i]>='0'&&c[i]<='9')
{
t=1;d=1;
for(j=i+1;j<l;++j)
{
if(c[j]>='0'&&c[j]<='9')t++;//统计该数位数
else break;
d*=10;
}
for(j=1;j<=t;++j)//将读到的字符串转化为实际意义的数
{
x=x+d*(c[i+j-1]-'0');
d/=10;
}
if(i-1>=0)//避免下标越界
{
if(c[i-1]=='-')
x=-x;
}
if(p==1||x>max)//如果这是第一个数或这个数大于max 则max=该数
{
max=x;
s=i+1;//记录最大数位置
if(i-1>=0)
{
if(c[i-1]=='-')
s=i;
}
}
i=i+t-1;
p++;
}
}
printf("%d\n",s);
}
7 最简IPv6表示
注意特殊情况 开头结尾的双冒号 以及只有双冒号的情况
优秀好同学平杰提供一份代码 以及混子的一份杂乱代码
大佬平杰:
#include<stdio.h>
#include<string.h>
int main()
{
int i, f, j, g, n,h, a[8], imax,imin, flage;
char s[40];
while(scanf("%s",&s)!=EOF)
{
imin=imax=1;
f=g=h=0;
n=strlen(s);
for(i=0;i<n;i++)//判断数据是否合法
{
if(!(s[i]>='0'&&s[i]<='9'||s[i]>='A'&&s[i]<='F'||i%5==4&&s[i]==':'))
f=1;
}
if(f||(n!=39)) printf("It's not a IPv6 address!\n");
else
{
flage =1;
sscanf(s,"%X:%X:%X:%X:%X:%X:%X:%X",&a[0],&a[1],&a[2],&a[3],&a[4],&a[5],&a[6],&a[7]);
for(i=0;i<8;i++)
{
if((a[i]==0)&&(a[i+1]==0)&&flage)//flag标记是否简写过多个零
{
imin=i;//imin标记多个零的开始位置
flage=0;
for(j=i+1;j<8;j++)
{
if(a[j]==0)
imax=j+1;//iMax标记多个零的结束位置
else
break;
}
if(j==8) h=1;//特殊情况:多个零在末尾(与第49行结合)
g=1;
}
}
if(imin==0) printf(":");//特殊情况:多个零在首
for(i=0;i<imin;i++)
printf("%X:",a[i]);
for(i=imax;i<8;i++)
{
if(g) printf(":");// 第一次不输出‘:’
printf("%X",a[i]);
g=1;
}
if(h) printf(":");
printf("\n");
}
}
return 0;
}
混子:
#include<stdio.h>
#include<string.h>
int main()
{
char c[50];
char x[8][50];
int i,j,t,g,tr,k,flag;
while(gets(c))
{
flag=1;
tr=1;
k=0;
for(i=0;i<=7;++i)
{
t=4;
strcpy(x[i],c+i*5);//意思为从c的第i*5个元素开始读
for(j=0;j<t;++j)
{
if(x[i][j]<'0'||x[i][j]>'9'&&x[i][j]<'A'||x[i][j]>'F')//检测是否合法
{
tr=0;
printf("It's not a IPv6 address!\n");
break;
}
}
if(tr==0)break;
}
if(tr==1)
{for(i=0;i<=7;++i)
{
t=4;
for(j=0;j<t;++j)//去除前导0
{
if(x[i][j]=='0')
{
for(g=j;g<t-1;++g)
{
x[i][g]=x[i][g+1];
}
t--;
j--;
}
else if(x[i][j]!=0)break;
}
x[i][t]='\0';//在最后一位之后加字符串的结束
}
for(i=0;i<=7;++i)
{
if(k)
printf(":");
if(x[i][0]=='\0')
{
for(j=i;j<=6;++j)
{
if(x[j+1][0]!='\0')break;
}
if(j==i||flag==0)printf("0");//flag代表是否有过双冒号
else
{
if(i==0||j==7)printf(":");//双冒号在最前或最后多加一个:
if(i==0&&j==7)printf(":");//全部数据都为0时
i=j;flag=0;
}
}
else printf("%s",x[i]);
k=1;
}
printf("\n");}
}
return 0;
}
8 回文数
涉及进制转换 以及回文数的判断
#include<stdio.h>
#include<string.h>
int main()
{
int a,i,j,d,g;
char c[31],s[31];
while(scanf("%d",&a)!=EOF)
{
for(i=1;i<=300;++i)//原数进制转换
{
d=i;
g=-1;
while(d)
{
g++;
if(d%a<10)s[g]=d%a+'0';
else s[g]=d%a-10+'A';
d/=a;
}
s[g+1]='\0';//字符串以\0结尾
strrev(s);//读进的数是反的,需要逆序
d=i*i;
g=-1;
while(d)//平方数进制转换
{
g++;
if(d%a<10)c[g]=d%a+'0';
else c[g]=d%a-10+'A';
d/=a;
}
c[g+1]='\0';//字符串以\0结尾
if(g%2==1)//分两种情况判断是否为回文数
{
for(j=0;j<=g/2;++j)
{
if(c[j]!=c[g-j])break;
}
if(j==g/2+1)printf("%s %s\n",s,c);
}
else
{
for(j=0;j<=g/2-1;++j)
{
if(c[j]!=c[g-j])break;
}
if(j==g/2)printf("%s %s\n",s,c);
}
}
}
return 0;
}
9 二元多项式求和
二维数组
#include<stdio.h>
#include<string.h>
int main()
{
int n,p[30][30]={0},i,j,k=0,a,b,c;
scanf("%d",&n);
for(i=1;i<=n;++i)//存入多项式
{
scanf("%d%d%d",&a,&b,&c);
p[a][b]+=c;
}
scanf("%d",&n);
for(i=1;i<=n;++i)//存入多项式
{
scanf("%d%d%d",&a,&b,&c);
p[a][b]+=c;
}
for(i=0;i<=20;++i)//按xy顺序输出
{
for(j=0;j<=20;++j)
{
if(p[i][j]!=0)
{
printf("%d %d %d\n",i,j,p[i][j]);
}
}
}
return 0;
}
10 二分查找
请大家参考C语言实验指导p113二分查找。
在书中基础上加上返回编号最小的功能。
#include<stdio.h>
int x[1000010];
int main()
{
int a,i,j,n,l,r,flag,s;
while(scanf("%d",&n)!=EOF)
{
flag=0;
for(i=1;i<=n;++i)
{
scanf("%d",&x[i]);
}
scanf("%d",&a);
l=1;r=n;
while(l<=r)//二分查找
{
if(x[(l+r)/2]==a)
{
flag=1;
break;
}
else if(a>x[(l+r)/2])l=(l+r)/2+1;
else r=(l+r)/2-1;
}
if(flag==1)
{
s=(l+r)/2;
for(i=(l+r)/2;i>=1;--i)//找到相同数最小编号
{
if(x[i]!=x[(l+r)/2])break;
s=i;
}
printf("%d\n",s);
}
else printf("None\n");
}
return 0;
}
11 搬桌子
可用循环将每次搬过的位置+10分钟 找出时间最久的位置,输出其时间
#include<stdio.h>
int main()
{
int max,d,i,j,l,a,b,t,n;
scanf("%d",&t);
for(i=1;i<=t;++i)
{
max=0;
int x[200]={0};
scanf("%d",&n);
for(j=1;j<=n;++j)
{
scanf("%d%d",&a,&b);
if(a>b)
{
d=a;a=b;b=d;
}
for(l=(a-1)/2;l<=(b-1)/2;++l)//搬过的位置加10min
{
x[l]+=10;
if(x[l]>max)max=x[l];//找最大
}
}
printf("%d\n",max);
}
return 0;
}
12 祝福玉树
可以先输出前两行,从第三行到第n行输出倒三角
#include<stdio.h>
int main()
{
int a,i,j;
while(scanf("%d",&a)!=EOF)
{
//第一行输出
printf(" ");
for(i=1;i<=a-5;++i)
printf("#");
for(i=1;i<=5;++i)
printf(" ");
for(i=1;i<=a-5;++i)
printf("#");
printf("\n");
//第二行输出
for(i=1;i<=a-3;++i)
printf("#");
for(i=1;i<=3;++i)
printf(" ");
for(i=1;i<=a-3;++i)
printf("#");
printf("\n");
//输出第三行到最后一行
for(i=1;i<=a-2;++i)
{
for(j=1;j<=i;++j)
printf(" ");
for(j=1;j<=a*2-3-i*2;++j)
printf("#");
printf("\n");
}
printf("\n");
}
return 0;
}
13 MM的PP照
此题若是直接计算每一个矩阵必定超时。
(代表位置)123 12 23
456 45 56
由题意 若是满足要求 则小矩阵1+5<=4+2 小矩阵2+6<=3+5 ,将二式相加得到:
1+2+5+6<=2+3+4+5-------1+6<=3+4----------即大矩阵要满足的要求
每一个大矩阵的成立条件都可以转化为多个小矩阵成立条件相加
故只需要判断小矩阵条件成立即可
#include<stdio.h>
int x[1000][1000];
int main()
{
int a,b,i,j,k;
while(scanf("%d%d",&a,&b)!=EOF)
{
k=1;
for(i=0;i<a;++i)
{
for(j=0;j<b;++j)
{
scanf("%d",&x[i][j]);
}
}
for(i=0;i<a-1;++i)
{
for(j=0;j<b-1;++j)
{
if(x[i][j]+x[i+1][j+1]>x[i+1][j]+x[i][j+1])//判断小矩阵是否满足条件
k=0;
if(k==0)break;
}
if(k==0)break;
}
if(k==1)printf("Yes\n");
else printf("No\n");
}
return 0;
}
14 密文转换
gets()读取,每个字母转化为五位二进制输出,遇到空格输出 //
#include<stdio.h>
#include<string.h>
int main()
{
char c[80];
int d,i,j,l,flag=0,k=0;
gets(c);
l=strlen(c);
for(i=0;i<l;++i)
{
if(c[i]!=' ')
{
if(c[i]>=65&&c[i]<=90)
c[i]=c[i]-'A'+1;
else
c[i]=c[i]-'a'+1;
char a[6]="00000";
a[5]='\0';
j=0;
d=c[i];
while(d)
{
a[j]=d%2+'0';
d/=2;
j++;
}
if(k)
printf(" ");
strrev(a);
printf("%s",a);
k=1;
flag=1;
}
else
{
if(flag)
{
printf(" //");
}
}
}
printf("\n");
return 0;
}
15 桃子的可达数
找到规律 所有超过10的数按其要求,最终都会回到 小于10的数 并在1-9反复循环。
所以对于大于等于10的数,可以先在计数器中加上他本身即1-9的数,即总数s=10,然后循环计数,直到该数小于10。
对于小于10的数,其总数便是9。
#include<stdio.h>
#include<string.h>
int main()
{
int bian(int a);//自定义函数原数+1并去除后导0
int t,n,i,j,s,g;
scanf("%d",&t);
for(i=1;i<=t;++i)
{
g=0;
scanf("%d",&n);
if(n>=10)
{
s=10;
while(1)
{
n=bian(n);
if(n<10)break;
s++;
}
}
else s=9;
printf("%d\n",s);
}
return 0;
}
int bian(int a)
{
a++;
while(1)
{
if(a%10==0)a/=10;
else return(a);
}
}