找规律(做个这类题目的汇总吧)

1.找规律(头歌平台的):

题目描述:

题目中会给你一个整数数组 num,num=[1,2,2,3,3,3…],然后题目中会给你一个整数 k,现在请你找出 num 的规律,并编写代码计算数组的前 k 项和为多少?

输入输出格式

输入格式
一个整数k。

输出格式
一个整数。

输入输出样例1

输入
5

输出
11

输入输出样例2

输入
10

输出
30

解题思路:

看题目可以看出他的规律是数组num以1开始,每个数字重复出现的次数等于它本身的值。换句话说,数组的第一个元素是1,第二个元素是2,第三个和第四个元素是2,第五个、第六个和第七个元素是3,以此类推。

参考代码:

#include<stdio.h>
void f(int *num,int c,int b)
{
    (*num)+=c*b;
}
int main()
{
    int k;
    scanf("%d",&k);
    int num=0;//前k项和
    int b=1;//数组元素值
    int c;//部分重复元素的数量
    for(int i=0;i<k;)//i是当前项
    {
       if(i+b>k)//当当前元素加上下一个元素的数量b超过了k时,意味着我们只需要部分重复下一个元素,此时c就表示这部分重复的数量
       {
           c=k-i;
           f(&num,c,b);
       }
       else {
           f(&num,b,b);//未超出时,
       }
       i+=b;//更新当前项
       b+=1;
       
    }
    printf("%d",num);
}

还有一种解法:

#include <stdio.h>

int main() {
    int k;
    scanf("%d", &k);
    int sum = 0;//前k项和
    int count = 0;//项数
    
    for (int i = 1; count < k; i++) { //i是数组元素,
        for (int j = 0; j < i && count < k; j++) { //j是重复元素数量
            sum += i;
            count++;//记录已经累加的项数,确保只累加了前k项
        }
    }
    printf("%d", sum);
    return 0;
}

2.蛇行矩阵(dotcpp 题号为1097):

题目描述

蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形。

输入格式

本题有多组数据,每组数据由一个正整数N组成。(N不大于100)

输出格式

对于每一组数据,输出一个N行的蛇形矩阵。两组输出之间不要额外的空行。矩阵三角中同一行的数字用一个空格分开。行尾不要多余的空格。

样例输入

5

样例输出

1 3 6 10 15
2 5 9 14
4 8 13
7 12
11

解题思路:

在这里插入图片描述

可以设行的增加数为count,列的增加数为c,可以看出初始c=count+1,

参考代码:

#include<stdio.h>
int main()
{
	int n;
	scanf("%d",&n);
	int count=1,count1=1;//count是行增加数,count1是每行第一个数
	for(int i=n;i>=1;i--)//每行上的数是逐渐递减
	{
	    
	    int t=0;//处理行尾没有多余的空格
	    int b=count1;//把b变为每行第一个数,在内循环递增推出后面的数
	    int c=count+1;//每一行中列增加的数
	    for(int j=1;j<=i;j++)//每行数的个数
	    {
	        if(t!=0)
	        printf(" ");
	        printf("%d",b);
	        b+=c;
	        c++;
	        t++;
	    }
	    printf("\n");
	    count1+=count;
	    count++;
	}
	return 0;
}

3.反反复复(dotcpp上题号为2895)

题目描述

Mo和Larry发明了一种信息加密方法。他们首先决定好列数,然后将信息(只包含字母)从上往下依次填入各列,并在末尾补充一些随机字母使其成为一个完整的字母矩阵。例如,若信息是“There’s no place like home on a snowy night”并且有5列,Mo会写成:
t o i o y
h p k n n
e l e a i
r a h s g
e c o n h
s e m o t
n l e w x
注意Mo只会填入字母,且全部是小写形式。在这个例子中,Mo用字母“x”填充了信息使之成为一个完整的矩阵,当然他使用任何字母都是可以的。
Mo根据这个矩阵重写信息:首先从左到右写下第一行,然后从右到左写下第二行,再从左到右写下第三行……以此左右交替地从上到下写下各行字母,形成新的字符串。这样,例子中的信息就被加密为:toioynnkpheleaigshareconhtomesnlewx。
你的工作是帮助Larry从加密后的信息中还原出原始信息(包括填充的字母)。

输入格式

第一行包含一个整数(范围2到20),表示使用的列数。
第二行是一个长度不超过200的字符串。

输出格式

一行,即原始信息。

样例输入

5
toioynnkpheleaigshareconhtomesnlewx

样例输出

theresnoplacelikehomeonasnowynightx

解题思路:

这题也可以当找规律来做,也许本意不是用种方式来做的
这是原来的样子:
t o i o y
h p k n n
e l e a i
r a h s g
e c o n h
s e m o t
n l e w x
这是加密后的:
t o i o y //可以看出奇数行未反写
n n k p h //偶数行是反着的,
e l e a i
g s h a r
e c o n n
t o m e s
n l e w x

题目要求的输出很随意,可以写一个函数每次遍历出一列,函数循环n次,
第一次时起始元素为第一列第一个,第二次起始元素为第二列第一个,以此类推,到最后一列时遍历完时,也就全打印出来了
可以看出加密后,原始信息中当前字母在奇数行时,则跟下个字母距离为2*n-1,n是输入的列数,但这个n是递减的,因为遍历过程中起始元素会往后一个,而下一个元素会往前一个,当前字母在偶数数行时,开始距离b为1,后续每次距离为b=b+2,是因为后面遍历过程中的下一个元素会往前一个,
请添加图片描述

参考代码:

#include <stdio.h>
#include <string.h>
void print(char s[201], int len, int row, int column, int i) {
    static int b = 1;//字母在偶数行时,与下一元素距离
    for (int j = 1; i < len && j <= row; j++) {
        printf("%c", s[i]);//输出元素
        if (j % 2) {//为奇数行时
            i += 2 * column - 1;
        } else {//为偶数行时
            i += b;
        }
    }
    b += 2;
}

int main() {
    int column;
    scanf("%d", &column);//列数
    char s[201];//加密后的字符串
    scanf("%s", s);
    int len = strlen(s);
    int cols = column;//列数
    int row = len / column;//得出行数
    for (int i = 0; i < column; i++) {
        print(s, len, row, cols, i);
        cols--;//奇数行下一字母距离的变化,解题思路中的n
    }
    return 0;
}


4.Peter 的烟(头歌平台上的):

题目描述

Peter 有 n 根烟,他每吸完一根烟就把烟蒂保存起来,k(k>1)个烟蒂可以换一个新的烟,那么 Peter 最终能吸到多少根烟呢?

吸烟有害健康。

输入格式

每组测试数据一行包括两个整数 n,k(1<n,k≤pow(10,8) )。

输出格式

对于每组测试数据,输出一行包括一个整数表示最终烟的根数。

输入输出样例

输入1
4 3
输出1
5
输入2
10 3
输出2
14

解题思路:

假设他吸的烟为sum,首先他肯定能吸到n根烟,所以sum初值为n,k根抽完的烟可以换根新烟,假设a为抽完的烟,a的初值为n,
可以写一个循环sum+=a/k,加上换的新烟,a=a/k+a%k,更新抽完的烟数,当a<k时跳出循环

参考代码:

#include<stdio.h>
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    int sum=n;
    int a=n;
    while(a>=k)
    {
        sum+=a/k;
        a=a/k+a%k;
    }
    printf("%d",sum);
    return 0;
}

题外话:
其实这题我在哪做过类似的,算这个题目进阶版,把这个题改一下,就是当烟蒂还差一个就可以换一根新烟时,可以先赊一根烟,抽完了刚好烟蒂够换一根烟,抵消掉了

参考代码:

#include<stdio.h>
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    int sum=n;
    int a=n;
    while(a>=k)
    {
        sum+=a/k;
        a=a/k+a%k;
        
    }
    if((k-a)==1)//并无多大改动,加个if语句判断即可
    {
       sum++;
    }
    printf("%d",sum);
    return 0;
}

5.位置的数量(头歌平台上的)

题目描述

彼得站在 n个人的队伍中,但他不知道自己究竟占据了哪个位置。 他只能知道,站在他面前的人不少于a人,站在他身后的人不超过b人。 请找出 Petr 可以占据的不同位置的数量。

输入格式

** 在同一行的数据均用空格分隔。 **
唯一一行包含三个整数 n、a和 b(0≤a,b<n≤100)。

输出格式

打印单个数字 。

输入输出样例

输入
3 1 1

输出
2

解题思路:

代码很简单,这题主要在于思路,
题目中说有n个人,也就是有n个位置,在他前面的人不少于a人,也就是说前面至少有a个位置,后面不超过b人,也就是后面至多有b个位置,注意求的是Petr可以在哪些位置的位置数量
用数轴来看待,前面一到a不能占,由于后面的限制,Petr能占到最前面的位置是n-b,
就有两只情况:

(1)当n-b大于a,也就是在a后面时,那么Petr能占的位置在[n-b,n]区间,能占的位置数量为b+1

(2)当n-b<=a时,也就是在a前面,那么Petr能占的位置在(a,n]区间,a那边是开,能占的位置是n-b

参考代码:

#include<stdio.h>
int main()
{
    int n,a,b;
    scanf("%d%d%d",&n,&a,&b);
    int c=n-b;//Petr能占的前面的位置
    if(c>a)
    {
     printf("%d",b+1);   
    }
    else if(c<=a)
    {
        printf("%d",n-a);
    }
    return 0;
}

6.有趣的扑克游戏(头歌平台上的):

题目描述

期末考试就要来临了,大家都在紧张的复习。作为在考场拼搏了十几载的当代大学生,小明和小华更懂得考前的放松。他们在每天晚上休息之前都要玩一会儿扑克牌以放松神经。
他们打牌的规则是这样的:

总共 n 张牌;
双方轮流抓牌;
每人每次抓牌的个数只能是 2 的幂次,即 1,2,4,8,16 等。
抓完牌,胜负结果也出来了,最后抓完牌的人为胜者;
假设小明和小华都足够聪明,并且每次都是小明先抓牌,请问谁能赢呢?

输入输出格式

输入格式
输入包含一个整数 n,表示扑克牌的数量。
输出格式
针对输入,如果小明能赢的话,请输出 ming,否则请输出 hua。

输入输出样例1

输入
1
输出
ming

输入输出样例2

输入
3
输出
hua

解题思路:

题目说轮流抓牌,最后抓完牌的人为胜者,小明先抓,假设抓了a次牌,若a为奇数,则就是小明赢,为偶数是小华赢,可以细细体会下,不难理解
再看每次抓牌只能是2的幂次,若总牌数为n,那我们就每次n对2进行取余,取余次数就为a,为1或0时停止,为1时a要加1

参考代码:

#include<stdio.h>
int main()
{
    int n;
    scanf("%d",&n);
    if(n%2==0)
        {
          printf("ming");
          return 0;
        }
        int a=0;
    while(n)
    {
        n=n%2;
        a++;
        if(n==1)
        {
            a++;
            break;
        }
    }
    if(a%2==0)
    {
        printf("hua");
    }
    else
    {
        printf("ming");
    }
    return 0;
}

7.ISBN码(dotcpp上1273)

题目描述

每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”就是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔符后的五位数字代表该书在该出版社的编号;最后一位为识别码。

识别码的计算方法如下:

首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod 11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。例如ISBN号码0-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2,…,9,再求和,即0×1+6×2+……+2×9=158,然后取158 mod 11的结果4作为识别码。

你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出你认为是正确的ISBN号码。

输入格式

  输入只有一行,是一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。 

输出格式

  输出共一行,假如输入的ISBN号码的识别码正确,那么输出“Right”,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符“-”)。

样例输入

0-670-82162-4
0-670-82162-0

样例输出

Right
0-670-82162-4

解题思路:
这题挺好做的,题目的意思很清楚,注意当得出的识别码为10,实际上识别为X的情况就好了
参考代码:

#include<stdio.h>
#include<string.h>
int main()
{
	char a[100];
	while(~scanf("%s",a))
	{
	    int b=0;//求识别码
	    int len=strlen(a);
	    int c=a[len-1]-'0';//把ISBN码取出来方便后面做对比
	    int k=1;//该数字是第几个,
	    for(int i=0;i<len-1;i++)
	    {
	        if(a[i]=='-')
	        continue;
	        b+=(a[i]-'0')*k;
	        k++;
	    }
	    b%=11;
	    if(b==c||(b==10&&a[len-1]=='X'))
	    {
	        printf("Right\n");
	    }
	    else if(b==10)
	    {
	        a[len-1]='X';
	        puts(a);
	    }
	    else
	    {
          a[len-1]=b+'0';
          puts(a);
	    }
	}
	return 0;
}

8.亲和数

题目描述

古希腊数学家毕达哥拉斯在自然数研究中发现,220的所有真约数(即不是自身的约数)之和为:

1+2+4+5+10+11+20+22+44+55+110=284。

而284的所有真约数为1、2、4、71、 142,加起来恰好为220。人们对这样的数感到很惊奇,并称之为亲和数。一般地讲,如果两个数中任何一个数都是另一个数的真约数之和,则这两个数就是亲和数。
你的任务就编写一个程序,判断给定的两个数是否是亲和数

输入格式

输入数据第一行包含一个数M,接下有M行,每行一个实例,包含两个整数A,B; 其中 0 <=A,B <=600000 ;

输出格式

对于每个测试实例,如果A和B是亲和数的话输出YES,否则输出NO。

样例输入

2
220 284
100 200

样例输出

YES
NO

解题思路:

求给出整数的约数和,从题意可看出只用求一个整数的约数和sum,然后与另一个数做对比即可,sum的初值为1,还有要注意是有多个测试实例,sum别忘了在下一次测试时初始化

参考代码:

#include<stdio.h>
#include<math.h>
int main()
{
	int m,a,b;
	scanf("%d",&m);
	for(int i=0;i<m;i++)
	{
	    int sum=1;//将约数和sum定义在循环中,这样每次循环都会初始化
	    scanf("%d %d",&a,&b);
	    for(int j=2;j<=sqrt(a);j++)//寻找约数,每次找出一对约数,加快速度
	    if(a%j==0)
	    sum=sum+j+a/j;
	    if(sum==b)//约数和等于另一个数则为亲和数
	    printf("YES");
	    else
	    printf("NO");
	    printf("\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值