tzoj萌新的思维训练

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;
}

千年幻想乡 ~ 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;
}

隐藏的最大整数

        字符串转化为数。

#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);
}

最简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;
}

 回文数

        涉及进制转换 以及回文数的判断

#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;
}

二元多项式求和

         二维数组

#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);
	}
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值