第十/十一届蓝桥杯笔记

1.平方和

思路:求出这样的数字,直接平方和;包含这样的数,只需对每一位数字进行检查,不断地取余,判断,再除10,对下一位数字取余,除完了循环终止;

代码:

#include<iostream>
using namespace std;

int main() {
    int n = 2019;
    int m;
    long long sum = 0;
    for (int i = 1; i <= n; i++)
    {
        int k = i;
        while (k) {
            m = k % 10;
            if (m==0||m == 2 || m == 1 || m == 9) {
                sum += i * i;
                break;
            }
            k /= 10;
        }
    }
    cout << sum;
}
1.2立方和
#include<iostream>
using namespace std;
typedef long long ll;

int main() {
    ll a,sum=0;
    for (int i = 1; i <= 2019; i++) {
        a = i;
        while (a) {
            if (a % 10 == 0 || a % 10 == 2 || a % 10 == 1 || a % 10 == 9) {
                sum += i*i*i;
                //cout << i << endl;
                break;
            }
            a = a / 10;
        }
    }
    cout<<sum<<endl;
}

2.数列求值

思路:最开始想到用数组直接求,递归或者迭代的思想,但是提示存放数组字节超出。由于题目仅仅需要输出后四位,加法只需要只计算后四位就行,因此可以只保留每一次计算的后四位数字。

注意:

大数组定义在main函数中?
数组定义在函数中时,占用的内存来自栈空间,栈空间是在进程创建时初始化的,有固定的大小,一般为几十KB,所以在main函数内部定义大数组相当于在栈内需要一个很大的空间,会造成栈的溢出。全局变量在静态存储区内分配内存,而局部变量是在栈内分配内存空间的。 因此,当我们需要定义一个极大的数组时,最好在main函数外部定义这个大数组。

代码如下:

#include<iostream>
using namespace std;
typedef long long ll;
const ll N = 20190324;

int a[N] = { 0 };

int main() {
    a[1] = a[2] = a[3] = 1;
    ll n=20190324;
    for (int i = 4; i <=n; i++) {
        a[i] = (a[i - 1] + a[i - 2] + a[i - 3])%10000;
    }
    cout << a[n];
}

3.字串数字

进制转化

#include<iostream>
using namespace std;
#include<string>
typedef long long ll;
int main() {
    string s;
    ll sum=0;
    cin >> s;
    for (int i = 0; i < size(s); i++)
    {
        sum = sum*26+s[i] - 'A' + 1;
    }
    cout << sum;
}

4.最大降雨量

/* * [][][][a][][][]

* [][][][b][][][]

* [][][][c][][][]

* [][][][max][][][]

* [][][][d][][][]

* [][][][e][][][]

* [][][][f][][][] * *

此题意思为将1至49分为7组数字,求取七组数字中每组数字的中位数所构成的数列的中位数的最大值 * 即如图所示,最大化[max] * 49个数字中需要比[max]大的有[max]行的后三位,d、e、f行的后四位,共3+3*4=15位 * 结果为:49-15=34 

5.质数

直接暴力:

#include<iostream>

using namespace std;

#include<math.h>

typedef long long ll;



int main() {

  ll sum=0,res=1;

  for (int i = 2; sum != 2019; i++) {

    int j = 2;

    for (; j <= sqrt(i); j++) {

      if (i % j == 0)

        break;

    }

    if (j > sqrt(i)) {

      sum++;

    }

    res = i;

  }

  cout << res;

}

6.迷宫

思路:

本题使用宽度优先搜索,主要核心是两个部分:

1.进行更新各点到终点的最短距离,这部分主要在于检查部分:除了边界点,障碍物点,未访问点,其中未访问点是以未更新最短距离为条件。其中计算最短距离是以终点为起点进行计算。

2.主函数部分,进行一次最短距离计算,从起点开始算,判断条件除了边界点,障碍物点,如果最短距离符合则为下一步该走的点。

代码:

#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
#include <queue>
using namespace std;
char a[40][60];                                                 //存图
int nextx[4] = { 1,0,0,-1 }, nexty[4] = { 0,-1,1,0 };           //D<L<R<U  方向数组按照字典序的顺序走   UD为x方向,LR为y方向
int dist[40][60];                                               //定义一个dist数组,用来存放各点到终点的最短距离
char dir[4] = { 'D','L','R','U' };
bool check(int x, int y) {                                       //判断边界以及是否访问
    return x > 0 && y > 0 && x <= 30 && y <= 50 && a[x][y] == '0' && dist[x][y] == -1;
}
void bfs() {                                                    //BFS扫一遍,求出各点到终点的最短距离
    queue<pair<int, int>>q;
    memset(dist, -1, sizeof(dist));                                //将dist数组中的所有字节的值设置为-1,用来标记未访问元素
    dist[30][50] = 0;                                              //终点到终点距离为0,用来设置终止条件
    q.push({ 30,50 });
    while (!q.empty()) {      //bfs运算
        pair<int, int> t = q.front();
        q.pop();

        for (int i = 0; i < 4; i++) {   
            int newx = t.first + nextx[i];   //按照定好的方向数组运算
            int newy = t.second + nexty[i];
            if (check(newx, newy)) {   //计算距离
                dist[newx][newy] = dist[t.first][t.second] + 1;
                q.push({ newx,newy });   //按宽度入队
            }
        }

    }
}

int main() {

    for (int i = 1; i <= 30; i++)   
        for (int j = 1; j <= 50; j++)
        {
            cin >> a[i][j];
        }
    bfs();                                                                             //调用一次bfs,计算出各点距离终点距离

    int x = 1, y = 1;                                                                       //从起点开始遍历
    string res;                                                                             //存答案
    while (x != 30 || y != 50) {                                            //只要不到终点便一直运行
        for (int i = 0; i < 4; i++) {
            int newx = x + nextx[i];
            int newy = y + nexty[i];
            if (newx > 0 && newy > 0 && newx <= 30 && newy <= 50 && a[newx][newy] == '0' && dist[newx][newy] == dist[x][y] - 1) {
                x = newx, y = newy;
                res += dir[i];
                break;
            }
        }
    }
    cout << res << "\n";
    return 0;
}

7.蛇形填数

把对角线的摘出来,1,5,13,25.......

看规律,第一行第一列是1,第二行第二列实际是 1+2+3-[3/2],第三行第三列是  1+2+3+4+5-[5/2]

第四行第四列就是  1+2+3+4+5+6+7-[7/2];

规律为  第n行第n列就是  1+2+....+(2n-1)-[(2n-1)/2];  

8.成绩分析

注意输出的时候   sum/n 将其强转成float就能保留小数位,printf("%.2f",(float)sum/n);就能保留两位小数

9.回文日期

暴力就行,注意添加检查条件:月份和日期的合法性,闰年二月合法性,大小月的合法性;

代码:

#include<iostream>
using namespace std;


int year, month, day;
int a[8];

bool check(int _year,int _month,int _day) {   //检查八位数日期合不合法
    if (_month == 2) {//闰年二月
        if ((_year % 4 == 0 && _year % 100 != 0) || (_year % 400 == 0)) {
            if (_day > 29)
                return false;
        }
        else {
            if (_day > 28)
                return false;
        }
    }
    if (_month > 12||_month==0 || _day > 31||_day==0)  //月,日
        return false;
    if (_month == 4 || _month == 6 || _month == 9 || _month == 11) {  //大小月
        if (_day > 30)
            return false;
    }
    return true;
}
void func(int N) {
    a[0] = N % 10;
    a[1] = (N / 10) % 10;
    a[2] = (N / 100) % 10;
    a[3] = (N / 1000) % 10;
    a[4] = (N / 10000) % 10;
    a[5] = (N / 100000) % 10;
    a[6] = (N / 1000000) % 10;
    a[7] = (N / 10000000) % 10;
    year = (N / 10000);
    month = (N / 100) % 100;
    day = N % 100;
}


int main() {
    int N;  //输入的八位数字
    cin >> N;
    bool tiao=false;
    
    for (int i = N+1; i < 99999999; i++) {
        //回文数
        func(i);
        if (a[0] == a[7] && a[1] == a[6] && a[2] == a[5] && a[3] == a[4] && !tiao) {
            if (check(year, month, day)) {
                cout << i << endl;
                tiao = true;
            }
        }
        if (a[0] == a[7] && a[1] == a[6] && a[2] == a[5] && a[3] == a[4]&& a[0] == a[2] && a[1] == a[3])
            if (check(year, month, day)) {
                    cout << i << endl;
                    break;
            }
    }
    return 0;
}

10.作物杂交

参考【蓝桥杯2020省赛】【深度优先搜索】作物杂交(详解!)-CSDN博客

代码如下:主要是利用递归解决,感觉挺像动态规划的方法。另外还学到了可以自定义一个结构体,再利用一个二维数组来存储所有的能得到该作物的杂交办法。不断地迭代来求能得到该作物的时间和父母作物的时间来求。

#include <iostream>
#include <algorithm>
#include "string.h"
#include <vector>
using namespace std;

struct parent //存储杂交方案
{
    int x;
    int y;
};
int n, m, k, t, tmp;
long long plant_time[2005];//每种作物的种植时间
bool flag[2005];//标记是否出现了该作物
long long min_hybrid_time[2005];//杂交出每种作物的最短时间
vector< vector<parent> >hybrid(2005);//存储每种作物的所有杂交方案

long long solve(int now)
{
    if (flag[now])//若是已有杂交出该种作物的最短时间
        return min_hybrid_time[now];//直接返回即可

    for (int i = 0; i < hybrid[now].size(); i++)//对能够杂交出当前作物的方案都尝试一下
    {
        parent tmp = hybrid[now][i];//能够杂交出当前作物的第i种方案
        //当前作物的最短杂交时间是 杂交出该作物的所有方案 中的最短时间
        //而每种方案的最短时间是种植其‘父母’作物所需要的时间 + 其父母作物杂交所需的的最短时间(=两者杂交所需时间中的最大值)
        min_hybrid_time[now] = min(min_hybrid_time[now], max(plant_time[tmp.x], plant_time[tmp.y]) + max(solve(tmp.x), solve(tmp.y)));
    }
    flag[now] = true;//标记已经找到最短杂交时间
    return min_hybrid_time[now];//返回最短杂交时间
}

int main()
{
    cin >> n >> m >> k >> t;
    memset(min_hybrid_time, 0x3f, sizeof(min_hybrid_time));//杂交出每种作物的最短时间初始化为最大值
    memset(flag, false, sizeof(flag));//作物标记初始化
    //注意作物的下标从1开始!!!
    for (int i = 1; i <= n; i++)//输入种植时间
        cin >> plant_time[i];
    for (int i = 0; i < m; i++)//输入初始种子数据
    {
        cin >> tmp;
        flag[tmp] = true;//标记已经有了最短杂交时间
        min_hybrid_time[tmp] = 0;//最短杂交时间 = 0,因为不需要杂交
    }
    for (int i = 0; i < k; i++)//输入所有杂交方案
    {
        parent temp;
        cin >> temp.x >> temp.y >> tmp;
        hybrid[tmp].push_back(temp);//存储杂交方案
    }
    solve(t);//递归求解
    cout << min_hybrid_time[t] << endl;//输出杂交出目标作物的最短时间
    return 0;
}

11.最短路

迪杰斯特拉

#include <iostream>
#include <cstring>
using namespace std;
const int N = 200, n = 19;
int dist[N];                                         //存储最短路的距离
int g[N][N];                                        //权值
void add(char x, char y, int c)                     //制作图的权值
{
    int a = x - 'A' + 1;                            //用ASKII码来实现对顶点进行排序
    int b = y - 'A' + 1;
    g[a][b] = g[b][a] = c;                          //赋权
}
bool vis[N];                                        //标记顶点是否处理过
int dijkstra()                                      //迪杰斯特拉算法
{
    memset(dist, 0x3f, sizeof dist);                //将顶点全部初始化为无穷大
    dist[1] = 0;                                    //初始化,从A到A的最短距离为0
    for (int i = 0; i < n; i++)
    {
        int t = -1;    //用于存放未访问的节点中距离起点最近的顶点的编号
        for (int j = 1; j <= n; j++)
        {
            if (!vis[j] && (t == -1 || dist[j] < dist[t]))   //如果未处理,且 顶点紧邻起点或者 
                t = j;
        }
        vis[t] = 1;          //标记已经处理完的顶点

        for (int j = 1; j <= n; j++)
        {
            dist[j] = min(dist[j], dist[t] + g[t][j]);        //更新最短路距离
        }
    }
    return dist[n];
}
int main()
{
    memset(g, 0x3f, sizeof g);
    add('A', 'B', 2);
    add('A', 'C', 1);
    add('A', 'D', 1);
    add('A', 'D', 1);
    add('B', 'J', 2);
    add('B', 'G', 1);
    add('C', 'D', 3);
    add('C', 'F', 3);
    add('C', 'G', 3);
    add('D', 'E', 1);
    add('D', 'G', 2);
    add('D', 'H', 1);
    add('D', 'I', 2);
    add('E', 'H', 1);
    add('E', 'I', 3);
    add('F', 'G', 1);
    add('F', 'J', 1);
    add('G', 'F', 1);
    add('G', 'I', 3);
    add('G', 'K', 2);
    add('H', 'I', 1);
    add('H', 'L', 2);
    add('I', 'M', 3);
    add('J', 'S', 2);
    add('K', 'N', 1);
    add('K', 'L', 3);
    add('K', 'P', 2);
    add('L', 'M', 1);
    add('L', 'R', 1);
    add('M', 'N', 2);
    add('M', 'Q', 1);
    add('M', 'S', 1);
    add('N', 'P', 1);
    add('O', 'P', 1);
    add('O', 'Q', 1);
    add('O', 'R', 3);
    add('R', 'S', 1);
   cout << dijkstra();
    return 0;
}

12.约数个数

#include<bits/stdc++.h>
using namespace std;


int main(){
	int n=78120;
	int sum=0;
	for(int i=1;i*i<n;i++){
		if(n%i==0){
			sum++;
		}
	}
	cout<<2*sum;
}

13.寻找2020

#include<iostream>
#include<string>
using namespace std;
char a[300][300];
int ant = 0;
void find1(int i, int j)
{
    if (a[i][j] != '2')
        return;
    //向右
    if (j + 3 < 300)
    {
        if ((a[i][j + 1] == '0') && (a[i][j + 2] == '2') && (a[i][j + 3] == '0'))
            ant++;
    }
    if (i + 3 < 300)
    {
        if ((a[i + 1][j] == '0') && (a[i + 2][j] == '2') && (a[i + 3][j] == '0'))
            ant++;
    }
    if ((j + 3 < 300) && (i + 3 < 300))
    {
        if ((a[i + 1][j + 1] == '0') && (a[i + 2][j + 2] == '2') && (a[i + 3][j + 3] == '0'))
            ant++;
    }
    return;
}
int main()
{
    for (int i = 0; i < 300; i++)
        for (int j = 0; j < 300; j++)
            cin >> a[i][j];
    for (int i = 0; i < 300; i++)
        for (int j = 0; j < 300; j++)
            find1(i, j);
    //cout << ant << endl;
cout<<16520<<endl;
    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值