目录
幻方
![](https://img-blog.csdnimg.cn/direct/525f6c8a9c75425eb1e544a37f7f7fd9.png)
思路:输入--->填数--->输出幻方
可以确定第一个数字1所填的位置,将1填入以后可以根据1的位置推出2的位置,由2的位置推出3的位置,依此类推,可以推到n*n的位置;当所填的数字超过n*n的时候可以结束循环。
简单地码亿下:
#include<stdio.h>
#include<string.h>
int main()
{
int n,kase = 2;
scanf("%d",&n);
int a[n][n];
memset(a,0,sizeof(a));
int x = 0,y = (n-1)/2;
a[x][y] = 1;
while(kase<=n*n){
if(x==0&&y!=n-1){
x = n - 1;
a[x][++y] = kase++;
}
else if(x&&y==n-1){
y = 0;
a[--x][y] = kase++;
}
else if(x==0&&y==n-1)
a[++x][y] = kase++;
else if(x&&y!=n-1&&a[x-1][y+1]==0)
a[--x][++y]=kase++;
else if(x&&y!=n-1&&a[x-1][y+1]!=0)
a[++x][y]=kase++;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(!j) printf("%d",a[i][j]);
else printf(" %d",a[i][j]);
}
printf("\n");
}
return 0;
}
PS:通过++x、++y、kase++等可以实现先移动再填数或者先填数再实现k+1,从而增强代码可读性。
冰雹猜想
![](https://img-blog.csdnimg.cn/direct/e5ffdc1996a545d688e694c820547621.png)
思路:只需要将每次操作得到的数字储存起来之后进行逆序输出即可,因此可以将其存到一个数组里面。将输入的n作为数组的第一个元素,根据n的奇偶得到新的数字作为下一个元素,依此类推直到将1存入数组(可以记下此时1存到了数组里的第几号元素)。最后只需要从1开始逆序输出。
所以,这个菜鸟写了代码如下:
#include<stdio.h>
int a[2000];
int main()
{
int n,kase=0,remind=0;
scanf("%d",&n);
a[0]=n;
for(int i=1;i<2000;i++){
if(n==1){
a[i]=n;
break;
}
if(n%2!=0)
n=3*n+1;
else
n/=2;
a[i]=n;
kase++;
}
for(int j=kase;j>=0;j--){
if(remind)
printf(" %d",a[j]);
else{
printf("%d",a[j]);
remind=1;
}
}
return 0;
}
显示屏
![](https://img-blog.csdnimg.cn/direct/765501d21dfd4464bc4e720c40d19177.png)
思路:第二行输入可以存到字符串里,使用的时候从最左边开始读取。显示屏上每个数字占据5行3列,每两个数字中间由一列 ' . ',于是可以考虑开辟二维数组,用这个数组充当显示屏,每读取一个数字就显示一个数字。那么可以通过一个计数器指向最左边的第0列,每显示一个数字就右移四列,这样每次只需要操作计数器指向的那一列及其右侧两列即可。
头脑风暴之后,写了代码如下:
#include<stdio.h>
#include<string.h>
int main()
{
int n,kase = 0;
scanf("%d",&n);
int num[5][4*n-1];
char a[n+1];
scanf("%s",a);
memset(num,'X',sizeof(num));
初始化“显示屏”
for(int i=0;i<5;i++){
for(int j=3;j<4*n-1;j+=4)
num[i][j] = '.';
}
让显示屏显示数字
for(int i=0;a[i]!='\0';i++){
if(a[i]=='0')
num[1][kase+1] = num[2][kase+1] = num[3][kase+1] = '.';
else if(a[i]=='1'){
for(int j=kase;j<=kase+1;j++){
for(int k=0;k<5;k++)
num[k][j] = '.';
}
}
else if(a[i]=='2'){
num[1][kase] = num[1][kase+1] =num[3][kase+1] =num[3][kase+2] = '.';
}
else if(a[i]=='3'){
for(int j=1;j<5;j+=2)
for(int k=kase;k<=kase+1;k++)
num[j][k] = '.';
}
else if(a[i]=='4'){
num[0][kase+1] = num[1][kase+1] = '.';
for(int j=3;j<5;j++)
for(int k=kase;k<=kase+1;k++)
num[j][k] = '.';
}
else if(a[i]=='5'){
num[1][kase+2] = num[1][kase+1] =num[3][kase] =num[3][kase+1] = '.';
}
else if(a[i]=='6'){
num[1][kase+1] = num[1][kase+2] = num[3][kase+1] = '.';
}
else if(a[i]=='7'){
for(int j=1;j<5;j++){
for(int k=kase;k<=kase+1;k++)
num[j][k] = '.';
}
}
else if(a[i]=='8'){
num[1][kase+1] = num[3][kase+1] = '.';
}
else if(a[i]=='9'){
num[3][kase] = num[3][kase+1] = num[1][kase+1] = '.';
}
kase+=4;
}
/输出
for(int i=0;i<5;i++){
for(int j=0;j<4*n-1;j++)
printf("%c",num[i][j]);
printf("\n");
}
return 0;
}
PS:输出的时候用%c,这样可以把存储的字符的ASCLL码(数字)转化输出为对应的字符。每个数字对应不同情况,进入分支(我觉得一定还有我没有想到的更好的显示数字的方法QWQ)
珠心算测验
![](https://img-blog.csdnimg.cn/direct/e62b070a10d8403b9367598f6708bd5f.png)
思路:将数字输入到数组中里面,每次都选出不同的两个数字求和,再将和与数组中的其他数字一一比对即可。
误区:求的和不能重复,比如1+4=5,2+3=5,但是5只能算一次;1+4与4+1也只算一组。
于是可以写一段长长的die码:
#include<stdio.h>
#include<string.h>
int kase = 0;
int judge(int d[],int t,int n){
for(int i =0;i<n;i++){
if(d[i]==t) return 0;
}
return 1;
}
int main()
{
int n,t,kase = 0;
scanf("%d",&n);
int a[n],d[n];
memset(d,0,sizeof(d));
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
t = a[i] + a[j];
for(int k = 0;k<n;k++){
if(a[k]==t&&judge(d,t,n)){
//printf("%d.%d + %d = %d\n",kase+1,a[i],a[j],a[k]);
d[kase] = t;
kase++;
}
}
}
}
printf("%d",kase);
return 0;
}
PS:当找到一组满足题意的时候,只需要把求的和存到另一个数组中,每次只需要再将求和与该数组中的元素比较,均不相同的时候才计数加一。
Bovine Bones G
![](https://img-blog.csdnimg.cn/direct/c75faf5058fa4498a7bb3b8aaa29aabb.png)
![](https://img-blog.csdnimg.cn/direct/93c92604f88d44c8aa0a19c430068378.png)
思路:三层循环计算总和,用桶排序处理。最小的情况是3,最大到80。
因此:
#include<stdio.h>
int main()
{
int s1,s2,s3;
int min,kase = 3;
int a[81] = {0};
scanf("%d%d%d",&s1,&s2,&s3);
for(int i=1;i<=s1;i++){
for(int j=1;j<=s2;j++){
for(int k=1;k<=s3;k++){
a[i+j+k]++;
}
}
}
min = a[3];
for(int i=3;i<=80;i++){
if(min<a[i]){
min = a[i];
kase = i;
}
}
printf("%d",kase);
return 0;
}
开灯
![](https://img-blog.csdnimg.cn/direct/d05b4a9d20294a729fb30264cd3b6080.png)
![](https://img-blog.csdnimg.cn/direct/24adf1bf4b9f4afd877593c76435cc3d.png)
思路:最多对2000000盏灯操作,可以开辟数组。假定开灯状态为1,关灯为0,则先使该数组内元素均为0;每当进行一次操作,就使对应的元素由1变为0或由0变为1;最后只需要遍历数组,找到1就可以输出编号。
#include<stdio.h>
int s[2000005] = {0};
void light(double a,int t){
for(int i=1;i<=t;i++){
int m = i*a;
if(s[m]==0) s[m] = 1;
else if(s[m]==1) s[m] = 0;
}
}
int main()
{
int x,t,i;
double a;
scanf("%d",&x);
for(i = 0;i<x;i++){
scanf("%lf%d",&a,&t);
light(a,t);
}
for(i = 1;s[i]==0;i++);
printf("%d",i);
return 0;
}
蛇形填阵
![](https://img-blog.csdnimg.cn/direct/ce115496dd564a9ab2a78602e2d824c9.png)
思路:开辟一个全为0的数组,从左上角开始填,那么第一个数字一定是1。外层通过循环控制填一圈数字,用每次填入的数字做判定条件即可。填数字的规律一定为先向右,然后经过判断转向下后填数,依次向左、向上填完每一圈。那么转弯的条件便可以是:未到达边界且将要填数的位置上为0。
#include<stdio.h>
#include<string.h>
int main()
{
int n,x = 0,y = 0;
scanf("%d",&n);
int a[n][n],t = 2;
memset(a,0,sizeof(a));
a[0][0] = 1;
while(t<=n*n){
while(y<n-1&&!a[x][y+1]) a[x][++y] = t++;
while(x<n-1&&!a[x+1][y]) a[++x][y] = t++;
while(y>0&&!a[x][y-1]) a[x][--y] = t++;
while(x>0&&!a[x-1][y]) a[--x][y] = t++;
}
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
printf("%3d",a[i][j]);
if(i!=n-1)
printf("\n");
}
return 0;
}
PS:看资料说x、y、a[0][0]的赋值操作合并为一句: a[x=0][y=0] = 1
(o.O)
杨辉三角
![](https://img-blog.csdnimg.cn/direct/25b2bce828c64267b0c199a466803cdf.png)
思路:输出为三角形,只需要内层把变量循环到与外层循环变量一样就可以。两侧均为1,从第三行开始每个数字都等于该数字上方和左上方的数字之和。
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
int a[n][n];
for(int i=0;i<n;i++){
a[i][0] = a[i][i] = 1;
}
for(int i=2;i<n;i++){
for(int j=1;j<i;j++){
a[i][j] = a[i-1][j-1] + a[i-1][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++){
if(!j) printf("%d",a[i][j]);
else printf(" %d",a[i][j]);
}
printf("\n");
}
return 0;
}
MC:插火把
![](https://img-blog.csdnimg.cn/direct/dbe0abe326b446e0be3c6361eddbef52.png)
思路:首先需要开辟n*n的方阵,认为没有光亮和方块的地方为0,有光照或方块为1。个人认为如果直接对原方阵操作,那么需要考虑萤石火把找到的范围内有没有越界的情况,那么就需要对火把萤石的位置进行分支操作,较为麻烦。于是想到,可以开辟(n+4)*(n+4)的方阵,而原先开辟的方阵相当于处于正中间的n*n的方阵((0,0)相当于此时的(2,2),(n,n)相当于此时的(n+2,n+2)),这样,无论火把萤石在什么地方,光照范围都不会越界,而真正需要统计的只是中间方阵里面的0的数目,外圈就不需要考虑了。
所以:
#include<stdio.h>
#include<string.h>
int main()
{
int n,m,k,kase = 0;
scanf("%d%d%d",&n,&m,&k);
int a[n+4][n+4],x,y;
memset(a,0,sizeof(a));
//火把
for(int i = 0;i<m;i++){
scanf("%d%d",&x,&y);
x = x + 1;
y = y + 1;
//点亮环境
a[x+1][y+1] = a[x-1][y-1] = a[x+1][y-1] = a[x-1][y+1] = 1;
for(int j = x-2;j<=x+2;j++)
a[j][y] = 1;
for(int j = y-2;j<=y+2;j++)
a[x][j] = 1;
}
//萤石
for(int i = 0;i<k;i++){
scanf("%d%d",&x,&y);
x = x + 1;
y = y + 1;
//点亮环境
for(int j = x-2;j<=x+2;j++){
for(int t = y-2;t<=y+2;t++)
a[j][t] = 1;
}
}
for(int i = 2;i<=n+1;i++){
for(int j = 2;j<=n+1;j++)
if(a[i][j]==0)
kase++;
}
printf("%d",kase);
return 0;
}
压缩技术
![](https://img-blog.csdnimg.cn/direct/1771dafb84284fe497c01fbb44ab285f.png)
思路:开辟数组之后,可以让x=0、y=0,之后每输入一个数就进行一次填数操作,再通过对a[x][y]赋值进行填数(每当y=n的时候就转到下一行第一个开始填数),再实现填0和1交替进行就可以得到题目要求的点阵。最后输出就可以。
#include<stdio.h>
int main()
{
int n,t,kase = 0,m = 1,x,y;
scanf("%d",&n);
int a[n][n];
x = y = 0;
while(kase!=n*n){
scanf("%d",&t);
kase+=t;
//确定填1或0
if(m==0) m = 1;
else m = 0;
//依次填数
for(int i = 0;i<t;i++){
a[x][y] = m;
y++;
if(y==n){
y = 0;
x++;
}
}
}
//输出点阵
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
printf("%d",a[i][j]);
printf("\n");
}
return 0;
}
当然,可以首先把所有的元素都赋为0,这样只需要填1就可以,大体思路是差不多的(m的初始值为0):
while(kase<n*n){
scanf("%d",&t);
kase+=t;
//确定填1
if(m==0){
m = 1;
x+=t/n;
y+=t%n;
continue;
}
else{
//依次填1
for(int i = 0;i<t;i++){
a[x][y++] = m;
if(y==n){
y = 0;
x++;
}
}
m = 0;
}
}
压缩技术(续集版)
![](https://img-blog.csdnimg.cn/direct/401cf797c4af41bea182025058e3caba.png)
思路:首先输入点阵,那么需要用二维的字符数组来输入储存。这样, 每个位置都对应一个数字,只需要确定该数字是否连续相同、相同多少次就可以。在每次判断之后立刻输出次数即可。
#include<stdio.h>
int main()
{
char str[205][205];
int t = 0,N,i,j,kase1 = 0,kase2 = 0;
while(scanf("%s",str[t++])!=EOF);
printf("%d",t-1);
if(str[0][0]=='1') printf(" 0");
for(i = 0;i<=t;i++){
for(j = 0;j<=t;j++){
if(str[i][j]=='0'){
if(kase2) printf(" %d",kase2);
kase1+=1;
kase2 = 0;
}
else if(str[i][j]=='1'){
if(kase1) printf(" %d",kase1);
kase1 = 0;
kase2+=1;
}
}
}
kase1?printf(" %d",kase1):printf(" %d",kase2);
return 0;
}
每次都是发生数值变化的时候才输出之前统计的结果,输出之后就可以将其清零并统计当前数字的连续次数。通过判断kase1、kase2是否为零可以确定是否发生了数值变化。
方块转换
![](https://img-blog.csdnimg.cn/direct/64a782a1120b4638995ad805e20eaa10.png)
思路:用字符串数组输入,然后找出每一种情况下坐标对应关系,依次判断就可以。
不用自定义函数的话可以写这么一坨:
#include<stdio.h>
int main()
{
int n,kase = 0;
scanf("%d",&n);
char a[n+1][n+1],b[n+1][n+1],c[n+1][n+1];
for(int i = 0;i<n;i++)
scanf("%s",a[i]);
for(int i = 0;i<n;i++)
scanf("%s",b[i]);
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
c[i][n-1-j]=a[i][j];
}
while(1){
//方法一
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
if(a[i][j]!=b[j][n-1-i])
kase++;
}
if(!kase){
printf("1");
break;
}
kase = 0;
//方法二
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
if(a[i][j]!=b[n-1-i][n-1-j])
kase++;
}
if(!kase){
printf("2");
break;
}
kase = 0;
//方法三
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
if(a[i][j]!=b[n-1-j][i])
kase++;
}
if(!kase){
printf("3");
break;
}
kase = 0;
//方法四
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
if(a[i][j]!=b[i][n-1-j])
kase++;
}
if(!kase){
printf("4");
break;
}
kase = 0;
//方法五
//方法一
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
if(c[i][j]!=b[j][n-1-i])
kase++;
}
if(!kase){
printf("5");
break;
}
kase = 0;
//方法二
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
if(c[i][j]!=b[n-1-i][n-1-j])
kase++;
}
if(!kase){
printf("5");
break;
}
kase = 0;
//方法三
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
if(c[i][j]!=b[n-1-j][i])
kase++;
}
if(!kase){
printf("5");
break;
}
kase = 0;
//方法六
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++)
if(a[i][j]!=b[i][j])
kase++;
}
if(!kase){
printf("6");
break;
}
printf("7");
break;
}
return 0;
}
也可以把每一部分单独摘出来写成函数:每当发现不一样的两个元素就return 0,如果完全一样则在最后return 1。