蓝桥杯倒计时刷题

过不过的无所谓了,这几天专心备赛,认真刷题,把心思全用在刷题、背题、理解上,失败了对你后续的算法学习也有帮助,成功了,哈哈哈,我偷着乐儿。。。。

2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。

有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。

也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。

给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。

输入描述

输入包含一个八位整数 NN,表示日期。

对于所有评测用例,10000101 \leq N \leq 8999123110000101≤N≤89991231,保证 NN 是一个合法日期的 8 位数表示。

输出描述

输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。

输入输出样例

示例

输入

20200202

输出

20211202
21211212

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

#include <stdio.h>

#include <stdlib.h>

int Compare(int year,int month,int year);

int main(int argc, char *argv[])

{

  // 

  int date,year,month,day,p,a,flag1=0,flag2=0;

  scanf("%d",&date);

  year = date/10000;

  month = (date%10000)/100;

  day = date%100+1;

  for(;year<9999;year++)

  {

    for(;month<=12;month++){

      if(month==4||month==6||month==9||month==11)

        p=30;

      else if ((month==2)&&(((year%4==0)&&(year%100!=0))||(year%400==0)))

        p=29;

      else if(month==2)

        p=28;

      else

        p=31;

      for(;day<=p;day++){

        a=Compare(year,month,day);

        if((a==1)&&(flag1==0))

        {

          printf("%d\n",year*1000+month*100+day);

          flag1=1;

        }

        if((a==2)&&(flag2==0))

        {

          printf("%d\n",year*1000+month*100+day);

          flag2=1;

        }

        if((flag1==1)&&(flag2==1))

          goto END;

      }

      day=1;

    }

    month=1;

  } 

  END: ;

  return 0;

}

int Compare(int year,int month,int day)

{

  int a[4],b[2],c[2];

  a[0] = year/1000;

  a[1] = (year%1000)/100;

  a[2] = (year%100)/10;

  a[3] = year%10;

  b[0] = month/10;

  b[1] = month%10;

  c[0] = day/10;

  c[1] = day%10;

  if((a[1]==a[3])&&(a[3]==b[0])&&(b[0]==c[0])&&(a[0]==a[2])&&(a[2]==b[1])&&(b[1]==c[1]))

        return 2;

    if((a[3]==b[0])&&(a[2]==b[1])&&(a[1]==c[0])&&(a[0]==c[1]))

        return 1;

    else

    return 0;

}

DFS

全排列问题:输出自然数 1 到 n所有不重复的排列,即 n的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

思想:调用函数每次选一个数,1个for循环遍历从1到n的所有数,选一个数,把数字存进数组并且标记该数,再调用选第二个数,for循环遍历数字存进数组并且标记该数,如此反复一直到选到n+1位数时,输出n位数字

#include<iostream>
using namespace std;
int number[100];//存答案
bool mark[100];//标记
int n;

void Dfs_(int ans);
int main()
{
    cin>>n;
    Dfs_(1);//从第一个数开始选
}
void Dfs_(int ans)
{
    if(ans == n+1)//递归基线条件,选到n+1个数停止
    {
        for(int j = 1;j<=n;j++){
            cout<<number[j];
        cout<<end1;
        return;//回溯
        }
    for(int i=1;i<=n;i++){
        if(mark[i]==false)//如果没有被标记过
        {
            number[ans]=i;
            mark[i]=true;//对该数进行标记
            Dfs_(ans+1);找下一个数
            mark[i]=false;//取消标记
            
        }    
    }
    }
}

2.选数:已知 n个整数 x1,x2,...xn,以及11个整数k(k<n。从n个整数中任选k个整数相加,可分别得到一系列的和。例如当n=4,k=3,4个整数分别为3,7,12,19时,可得全部的组合与它们的和为:

3+7+12=22

3+7+19=29

7+12+19=38

3+12+19=34

现在,要求你计算出和为素数共有多少种。

例如上例,只有一种的和为素数:3+7+19=29

//选数
//从四位选第一位,标记该数,并计算和
//从四位选第二位,并且没做过标记,并计算与第一位的和
//从四位选第三位,并且没做过标记,并计算与前两位的和
//直到选到第n位数,判断是否为素数,满足条件ans+1
#include<iostream>
#include<cmath>
using namespace std;

int number[25];//存数字
bool mark[10000000];//标记
int n,k,ans;

void Dfs_(int s,int sum,int i);//s用来选记住了几位数,sum用来计算选数的和,i用来记录
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>number[i];
    Dfs_(1,0,1);//从第一个数字开始选
    cout<<ans;
    }
}
void Dfs_(int  s,int sum,int i)
{
    if(s==k+1)
{
int j;
for(j=2;j<=sum;j++){
if(sum%j==0&&sum!=1;&&sum!=2)
break;
if(j==sum-1||sum==1||sum==2)
{
ans++;
}
}
return ;//回溯
}
for(i;i<=n;i++)
if(mark[i]==false)
{
mark[i]=true;
Dfs_(s+1,sum+number[i],i);
mark[i]=false;
}
}



地图问题 上左下右

#include<stdio.h>
int map[10][10];//布置初始化地图
int beat[10][10];//存入地图障碍点
int way_x[4]={1,-1,0,0};//选择上下左右四个方向
int way_y[4] = {0,0,1,-1};//同上
int start_x,start_y,end_x,end_y,ans=0;//开始坐标和结束坐标
int n,i,a,b,m,s;
void Dfs(int x,int y);
int main()
{

    int n,i,a,b,m,s,j;
    scanf("%d %d %d",&n,&m,&s);
    scanf("%d %d %d %d",&start_x,&start_y,&end_x,&end_y);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            map[i][j]=1;
    for(i=1;i<=s;i++)
{
scanf("%d %d",&a,&b);
map[a][b] = 0;//标记障碍物
}
Dfs(start_x,start_y);
printf("%d",ans);
}
void Dfs(int x,int y)
{

int i;
if(x==end_x&&y==end_y)
{
ans++;
return;
}
else{
for(i=0;i<=3;i++)//选择四个方向
if(map[x+way_x[i]][y+way_y[i]]==1&&beat[x+way_x[i]][y+way_y[i]]==0)
{

    beat[x][y]=1;
Dfs(x+way_x[i],y+way_y[i]);
beat[x][y]=0;
}

}
}

暴力

模拟

并查集

题目背景
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
题目描述
规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。
输入格式
第一行:三个整数n,m,p,(n<=5000,m<=5000,p<=5000),分别表示有n个人,m个亲戚关系,询问p对亲戚关系。
以下m行:每行两个数Mi,Mj,1<=Mi,Mj<=N,表示Mi和Mj具有亲戚关系。
接下来p行:每行两个数Pi,Pj,询问Pi和Pj是否具有亲戚关系。
输出格式
P行,每行一个’Yes’或’No’。表示第i个询问的答案为“具有”或“不具有”亲戚关系。

#include<cstdio>
#define MAXN 5005
int fa[MAXN],rank[MAXN]
inline void init(int n)
{

    for(int i =1;i<=n;i++)
        {
            fa[i] = i;
            rank[i] = 1;
        }

}
int find(int x)
{
    return x==fa[x]?x:(fa[x] = find(fa[x]));
}
inline void merge(int i.int j)
{
    int x = find(i),y=find(j);
    if(rank[x]<=rank[y])
        fa[x] = y;
     else
        fa[y] = y;
    if(rank[x]==rank[y]&&x!=y)
        rank[y]++;

}
int main()
{
    int n,m,p,x,y;
    scanf("%d%d%d",&n,&m,&p);
    init(n);
    for(int i =0;i<m;i++)
    {
        scanf("%d%d",&x,&y);
        merge(x,y);
    }
    for(int i =0;i<p;i++)
{
    scanf("%d%d",&x,&y);
    printf("%s\n",find(x)==find(y)?"Yes":"No");
}
    return 0;

}

二分

public int BinarySearch(int [] array,int n,int value){

    int low = 0;
    int high = n-1;
    while(low<=high){
        int mid = (low+high)/2;
        if(array[mid]>value){
            high = mid-1;
        }
        else if(array[mid]<value){
            low = mid+1;
        }
        else{
            return mid;
        }
    }
    return -1;
}

如果数组中有重复的元素

public int BinarySearch(int []a,int n,int value){

    int low = 0;
    int high = n-1;
    while(low<=high){
        int mid = low+((high-low)>>1);
        if(a[mid]>value){
            high = mid-1;
        }else if(a[mid]>value){
            low = mid+1;
        }else{
            if(mid==0)||(a[mid-1]!=value)return mid;
        else high = mid-1;
        }
    }
return -1;

}

二分法要处理的问题、

看如下数组: 

查找key=4的最小下标

#include<iostream>
using namespace std;
const int N=1e6;
int n,key,arr[N];
int binarySearch(int arr[],int n,int key)
{

    int l = 1;
    int r=n;
    int ans = -1;
    while(l<=r)
    {
        int m = l+(r-1)/2;
        if(arr[m]==key)//如果当前arr[m]等于key,看有没有更靠前的位置
        {

            ans = m;
            r = m-1;
        }else{l=m+1}
    }
return ans;
}
int main()
{

    cin>>n>>key;
    for(int i=1;i<=n;i++){cin>>arr[i];
        int ans = binarySearch(arr,n,key);
        cout<<ans;
        return 0;    

}
}

查找第一个大于或等于key=4的下标

#include<iostream>
using namespace std;
const int N=1e6;
int n,key,arr[N];
int binarySearch(int arr[],int n,int key)
{

    int l=1;
    int r = n;
    int ans =-1;
    while(l<=r){

        int m=l+(r-l)/2;
        if(arr[m]>=key)//如果当前arr[m]大于等于key看有没有更靠前的位置
        {
            ans = m;
            r = m-1;
        }
        else
        {
            l=m+1;
        }
    
    }
return ans;

}

int main()
{
    cin>>n>>key;
    for(int i=1;i<=n;i++)
        cin>>arr[i];
    int ans = binarySearch(arr,n,key);
    cout<<ans;
    return 0;
}

查找第一个大于key=4的下标

#include<iostream>
using namespace std;
const int N=1e6;
int n,key,arr[N];
int binarySearch(int arr[],int n,int key)
{

    int l=1;
    int r = n;
    int ans =-1;
    while(l<=r){

        int m=l+(r-l)/2;
        if(arr[m]>key)//如果当前arr[m]大于等于key看有没有更靠前的位置
        {
            ans = m;
            r = m-1;
        }
        else
        {
            l=m+1;
        }
    
    }
return ans;

}

int main()
{
    cin>>n>>key;
    for(int i=1;i<=n;i++)
        cin>>arr[i];
    int ans = binarySearch(arr,n,key);
    cout<<ans;
    return 0;
}

要统计key=4的个数

出题

题目是这样的:给出一串数以及一个数字 CC,要求计算出所有 A - B = CA−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。

输入格式

输入共两行。

第一行,两个整数 N, CN,C。

第二行,NN 个整数,作为要求处理的那串数。

输出格式

一行,表示该串数中包含的满足 A - B = CA−B=C 的数对的个数。

输入输出样例

输入 #1复制

4 1
1 1 2 3

输出 #1复制

3

分析:既然是找出A-B=C的情况。

第一步,从这n个数字中枚举确定A,这一步时间复杂度为O(n),一旦选取了A,因为B=A+C,说明B也就确定了。

第二步,从n个数字中查找B的个数num,从n个数中查找B的个数,就是用上面的upperBound-lowerBound的方法求解,时间复杂度为O(logn)。

将num都累加起来保存到ans中。

那么,ans就是最终答案。

综合分析:通过第一步,第二步,整个题目的时间复杂度为O(nlogn),就可以顺利过了。

#include<iostream>
#includeusing namespace std;
const int N=2e5+10;
int n,c,arr[N];
typedef long long ll;
int lowerBound(int key)//查找第一个大于或等于key的位置
{

    int l=1,r=n;
    int ans = 0;
    while(l<=r){
        int mid = l+(r-l)/2;
        if(arr[mid]>=key){ans = mid;r=mid-1;}
        else {l=mid+1;}
    }
    return ans;

}
int upperBound(int key){
    int l=1,r=n;
    int ans=0;
    while(l<=r)
    {
        int mid = l+(r-l)/2;
        if(arr[mid]>key)
        {ans = mid;r=mid-1;}else {l=mid+1;}
    }
return ans;
}

int main()
{

    cin>>n>>c;
    ll ans = 0;
    for(int i=1;i<=n;i++)
        cin>>arr[i];

    sort(arr+1,arr+1+n);
    for(int i=1;i<=n;i++){
        int a = arr[i];
        int b = a-c;
        //查找数列中b的个数
        ll res=upperBound(b)-lowerBound(b);
            ans +=res;
    }
    cout<<ans;
    return 0;
    

}

动态规划

贪心

BFS

int n=10,m=10;//地图宽高
void BFS()
{
    queue que;//用队列来保存路口
    int graph[n][m];//地图
    int px[] = {-1,0,1,0};//移动方向的数组
    int py[] = {0,-1,0,1};
    que.push(起点入列);//将起点入列
    while(!que.empty()){
        auto temp = que.pop();//将得到队列中的元素
        for(int i=0;i!=4;i++){
            if(//可以走){
                //标记当前格子
                //将当前状态入列,等待下次提取
}
}
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

撸码的xiao摩羯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值