【C++枚举题目】【对整数的每一位进行枚举】【对棋盘(二维数组)九宫格位置的枚举】【有理数的枚举——Cantor表】【连号区间数】【最大公约数和最小公倍数】【日期格式转换问题】

目录

【对整数的每一位进行枚举】

【对棋盘(二维数组)九宫格位置的枚举】

【有理数的枚举——Cantor表】

输入描述

输出描述

       【题解】

【连号区间数】

 【对连号区间的判断】

【最大公约数和最小公倍数】

【最大公约数】

【最小公倍数】

【日期格式转换问题】

【闰年的判断】

【日期的输入和输出格式】


【对整数的每一位进行枚举】

对于整数 a ,对 a 做如下操作,进行每一位的枚举

while(a!=0){
    m=a%10; //m即为从右到左,a的每一位
    a/=10;}

 对应题目:特别数的和 

【对棋盘(二维数组)九宫格位置的枚举】

        很多题目都会需要求一个元素周围九宫格的各个元素(如下图所示):

         我们可以把中间的元素设置为(0,0),那么它周围8个元素就可以表示出他们的相对位置,就可以得到下面的位置矩阵

int matrix[9][2]={
    {-1,-1},
    {-1,0},
    {-1,1},
    {0,-1},
    {0,0},  //为中间的元素
    {0,1},
    {1,-1},
    {1,0},
    {1,1}
  };

        根据相对位置矩阵,就可以根据中间元素来判断出其他8个元素的实际位置

对应题目:图像模糊 

                  灌溉 

【有理数的枚举——Cantor表】

        现代数学的著名证明之一是 Georg Cantor 证明了有理数是可枚举的。他是用下面这一张表来证明这一命题的:

1/1  1/2  1/3  1/4  1/5 …
2/1  2/2  2/3  2/4  …
3/1  3/2  3/3  …
4/1  4/2  …
5/1  …
…

        我们以 Z 字形给上表的每一项编号。第一项是 1/1,然后是 1/2,2/1,3/1,2/2,⋯

输入描述

        输入 1 个整数 N,   \left ( 1\leq N\leq 10^{7} \right ) 。

输出描述

        输出 表中的第 N 项。

 【题解】

         可以观察出来每一条线上的有理数都在递增,且每次递增1,可以设置一个累加和 S

S 的作用是确定 N 的范围,即确定 N 所在哪一条线上,设置这条线上有理数个数为 delt

      

        可以根据 S 与 N 的差值,确定 N 的位置

        具体代码如下:

#include <iostream>
using namespace std;
int main()
{
  int s=0;
  int delt=0;
  int N;
  cin>>N;
  while(s<N){
    delt++;
    s+=delt;
  }
  int i=s-N;
  if(delt%2==0){
    cout<<delt-i<<"/"<<1+i;
  }
  else
  {
    cout<<1+i<<"/"<<delt-i;
  }
  return 0;
}

【连号区间数】

        在 1 ~ N 的某个全排列中有多少个连号区间呢?

        这里所说的连号区间的定义是:

        如果区间 [L,R] 里的所有元素(即此排列的第 L 个到第 R 个元素)递增排序后能得到一个长度为 R−L+1 的"连续"数列,则称这个区间连号区间。

 【对连号区间的判断】

        根据连号区间的定义,我们能够得到结论:

        该区间的 max - min = 该区间的元素个数 。

        于是,我们可以利用双指针来解决此类问题。

        具体代码如下:

#include <iostream>
using namespace std;
#define M 500001
int main()
{
  int N;
  cin>>N;
  int arr[M];
  for(int i=1;i<=N;i++)
    cin>>arr[i];
  int count_num=0;
  for(int i=1;i<=N;i++){
    int max=0,min=N;
    for(int j=i;j<=N;j++){
      max=arr[j]>max?arr[j]:max;
      min=arr[j]<min?arr[j]:min;
      if(max-min==j-i)
        count_num++;
    }
  }
  cout<<count_num;
  return 0;
}

【最大公约数和最小公倍数】

【最大公约数】

       【辗转相除法】——直接上代码啦

int gcd(int x,int y){
  int min_num=min(x,y);
  int max_num=max(x,y);
  if(max_num%min_num==0)
    return min_num;
  return gcd(max_num%min_num,min_num);
}

【最小公倍数】

        最小公倍数 = x * y / 最大公约数

【日期格式转换问题】

【闰年的判断】

        闰年可以被400整除,可以被4整除但是不能被100整除:

bool j_ruen(int a){
  if(a%400==0||(a%100!=0&&a%4==0))
    return true;
    else return false;
}

 【日期的输入和输出格式】

        有的题目要求日期的输入格式为:(xx/xx/xx),此时可以用scanf();输出格式要求为: "yyyy−MM−dd",可以用printf()

        但是,在用 scanf()和 printf()的时候,需要加上以下头文件

#include <cstdio>
#define _CRT_SECURE_NO_WARNINGS
scanf("%d/%d/%d",&a,&b,&c);
printf("%d-%02d-%02d",year,month,date);
//02的意思是如果输出的整型数不足两位,左侧用0补齐

         更多的枚举题目可以参考如下文章:

C++各种常见枚举题目【水仙花】【三连击】【枚举矩形】【枚举日期】【枚举RGB区间】【01比特串法子集枚举】【和为3的倍数的子集数】【珠心算】【取宝石问题】_c语言枚举编程题_捡到一只姜小鱼的博客-CSDN博客

        本篇文章是对链接中文章的补充,更多关于枚举题目的巧妙方法可以参考链接中文章。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值