0
点赞
收藏
分享

微信扫一扫

第六届蓝桥杯题解

第六届蓝桥杯题解

前言

新蝙蝠侠太好看了!!!姥爷牛逼!!!
在这里插入图片描述
强推去看!!!!!

方程整数解

在这里插入图片描述
这道题可以直接暴力来写,答案有点坑,题目没有说不是负数!答案是 -30

#include <bits/stdc++.h>
using namespace std;
// 传送门:https://www.lanqiao.cn/courses/2786/learning/?id=67081
// 答案:-30
int main()
{
    int ans = -1;
    for (int i = 0; i <= 40; i++)
        for (int j = 0; j <= 40; j++)
            for (int z = 0; z <= 40; z++)
            {
                if (i * i + j * j + z * z == 1000)
                {
                    ans = max(ans, j);
                    ans = max(ans, z);
                    ans = max(ans, i);
                }
            }
    cout << "-" << ans;
    return 0;
}

星系炸弹

在这里插入图片描述
直接嗯模拟即可,其实也可以直接用excel来算 (太犯规了),代码解法贴在下面

#include <bits/stdc++.h>
using namespace std;
// 传送门:https://www.lanqiao.cn/courses/2786/learning/?id=67081
// 模拟
// 答案:2017-8-05
int month[2][13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
                    0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int main()
{
    int y, m, d;
    y = 2014;
    m = 11;
    d = 9;
    int sum = 1000;
    while (sum)
    {
        if (y % 4 == 0)
        {
            if (sum - (month[1][m] - d) < 0)
            {
                d += sum;
                sum = 0;
            }
            else
            {
                sum -= (month[1][m] - d);
                m++;
                d = 0;
                if (m == 13)
                {
                    m = 1;
                    y++;
                }
            }
        }
        else
        {
            if (sum - (month[0][m] - d) < 0)
            {
                d += sum;
                sum = 0;
            }
            else
            {
                sum -= (month[0][m] - d);
                m++;
                d = 0;
                if (m == 13)
                {
                    m = 1;
                    y++;
                }
            }
        }
    }
    cout << y << " " << m << " " << d;
    return 0;
}

奇妙的数字

在这里插入图片描述
直接暴力就完了,从1到1000枚举,算到谁是谁

#include <bits/stdc++.h>
using namespace std;
// 传送门:https://www.lanqiao.cn/courses/2786/learning/?id=67081
// 暴力枚举
int visit[10];
bool judge(int x, int y)
{
    int cnt1 = 0, cnt2 = 0;
    while (x)
    {
        visit[x % 10] = 1;
        cnt1++;
        x /= 10;
    }
    while (y)
    {
        visit[y % 10] = 1;
        cnt2++;
        y /= 10;
    }
    if (cnt1 + cnt2 != 10)
    {
        return false;
    }
    for (int i = 0; i < 10; i++)
    {
        if (visit[i] != 1)
            return false;
    }
    return true;
}
int main()
{
    for (int i = 1; i <= 10000; i++)
    {
        memset(visit, 0, sizeof(visit));
        if (judge(i * i * i, i * i))
        {
            cout << i;
        }
    }
    return 0;
}

格子中输出

在这里插入图片描述
在这里插入图片描述
这道题实属有点恶心,如果不知道printf的这种用法多半是寄了 (比如说我)
(width-2-strlen(buf))/2," “,buf,(width-2-strlen(buf)+1)/2,” "
因为它题目要求如果没有办法中间,要向左上靠,所以前面是除2,后面直接减去

九数组

在这里插入图片描述
在这里插入图片描述
这道题考察的是对深搜回溯的理解,dfs回溯写多的可以妙出答案
t = x[k], x[k] = x[i], x[i] = t;

牌型种数

在这里插入图片描述
在这里插入图片描述
简化一下模型,就是13种牌,每种牌有四张,然后取13张,有多少种取法
这道题解法很多:
首先是暴力枚举,直接枚举每种牌的个数,如果和能等于13就行

#include <stdio.h>
int main () {
 
	int ans = 0;
	for (int a = 0;a < 5;a++) {
		for (int b = 0;b < 5;b++) {
		for (int c = 0;c < 5;c++) {
		for (int d = 0;d < 5;d++) {
		for (int e = 0;e < 5;e++) {
		for (int f = 0;f < 5;f++) {
		for (int g = 0;g < 5;g++) {
		for (int h = 0;h < 5;h++) {
		for (int i = 0;i < 5;i++) {
		for (int j = 0;j < 5;j++) {
		for (int k = 0;k < 5;k++) {
		for (int l = 0;l < 5;l++) {
		for (int m = 0;m < 5;m++) {
		if ((a+b+c+d+e+f+g+h+i+j+k+l+m) == 13)
			ans++;
	}
		}
	}
		}
	}
		}
	}
		}
	}
		}
	}
		}
	}
	printf ("%d",ans);
	return 0;
}

还有就是用深搜来写
思路很巧妙,一开始没想到,想到就很容易

#include <bits/stdc++.h>
using namespace std;
// 传送门:https://blog.csdn.net/alidadaaaa/article/details/79690108?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164793048016780274131254%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164793048016780274131254&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-79690108.142^v3^pc_search_result_cache,143^v4^control&utm_term=%E7%89%8C%E5%9E%8B%E7%A7%8D%E6%95%B0&spm=1018.2226.3001.4187
// dfs
int ans;
void dfs(int n, int cardnum) // n是代表牌的花色,cardnum代表牌的总数
{
    if (n > 13)
    {
        return;
    }
    if (cardnum == 13)
    {
        ans++;
        return;
    }
    if (cardnum > 13)
    {
        return;
    }
    dfs(n + 1, cardnum);
    dfs(n + 1, cardnum + 1);
    dfs(n + 1, cardnum + 2);
    dfs(n + 1, cardnum + 3);
    dfs(n + 1, cardnum + 4);
}
int main()
{
    dfs(0, 0);
    cout << ans << endl;
    return 0;
}

手链样式

在这里插入图片描述

我们首先要理解它题目的转动和反转的意思
就好比AAABBBBCCCCC是一个链
首先我们理解第一个词,转动-----手链是一个环,所以说呢,我们先放第一个简单的情况进行类比
第一种情况就是 AAABBBBCCCCC,然后串成环,头部的A和尾部的C就连接起来了
现在我们进行一次转动,转动一个单位,字符串就成了AABBBBCCCCCA,但是呢,在手链这个环中,样式还是没变,也就是说,当我们转动其中一种情况的环时,同时能诞生出好几种不同字符串相同样式的环,这些情况就不能算进去。
另外一种情况翻转,翻转这种情况的实际上其实就是将手链转动一周,例如:AAABBBBCCCCC转动一周后就是CCCCCBBBBAAA。
因此综上所述,我们有效的处理这两种限制情况的办法就是构建一个新的字符串为两个字符串相拼接的结果。(temp = str + str)
参考大佬思路

#include <bits/stdc++.h>
using namespace std;
// 传送门:https://blog.csdn.net/bettle_king/article/details/115028506?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164793155016782184611226%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164793155016782184611226&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-115028506.142^v3^pc_search_result_cache,143^v4^control&utm_term=%E6%89%8B%E9%93%BE%E6%A0%B7%E5%BC%8F&spm=1018.2226.3001.4187
// 环上问题
int ans = 0;
vector<string> a;
int main()
{
    string tar = "AAABBBBCCCCC";
    do
    {
        bool flag = true;
        for (int i = 0; i < a.size(); i++)
        {
            if (a[i].find(tar) != string::npos) //假如在已经储存的字符串依次遍历找不到新字符串的子串
            {
                flag = false;
                break;
            }
        }
        if (!flag)
            continue;
        string remp1 = tar + tar;
        a.push_back(remp1);
        reverse(remp1.begin(), remp1.end());
        a.push_back(remp1);
        ans++;

    } while (next_permutation(tar.begin(), tar.end()));
    cout << ans;
    return 0;
}

另外补一下这个next_premutation的说明,这是stl内置求一个序列全排列的函数,可以自动枚举不同次序字符串
模板:

int a[]={1,2,3,4,5};
do
{
	for(int i=0;i<len;i++)
	cout<<a[i];
	cout<<endl;
}while(next_premutation(0,len-1))

next_premutation详解

饮料换购

直接模拟就行,老老实实按步骤来
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
// 传送门:http://lx.lanqiao.cn/problem.page?gpid=T2796
// 嗯模拟
int main()
{
    ios::sync_with_stdio(false);
    int num = 0;
    int ans = 0;
    int ping = 0;
    cin >> num;
    while (num)
    {
        num--;
        ans++;
        ping++;
        if (ping == 3)
        {
            ping = 0;
            num++;
        }
    }
    cout << ans;
    return 0;
}

垒骰子

在这里插入图片描述
这道题的题目很坑,当时做的时候看样例一脸懵逼,两个骰子为啥会有500多种方法?
其实可以想象一下,一个骰子,当朝上的方向固定时,它可以转动:
在这里插入图片描述
理解题意之后,可以考虑两种方式入手
第一种:深搜:(TLE)只能37分
这应该时考场上没有办法的办法了

#include <bits/stdc++.h>
using namespace std;
// http://lx.lanqiao.cn/problem.page?gpid=T2797
const long long mod = 1e9 + 7;
int link[7][7];
map<int, int> edge;
int n, m; // n个骰子,m个排斥关系
long long ans;
void start()
{
    edge[1] = 4;
    edge[2] = 5;
    edge[3] = 6;
    edge[4] = 1;
    edge[5] = 2;
    edge[6] = 3;
    for (int i = 1; i <= 6; i++)
        for (int j = 1; j <= 6; j++)
            link[i][j] = 1;
}
void dfs(int cnt, int up) // up代表上方数字
{
    if (cnt == n)
    {
        (ans++) % mod;
        return;
    }
    for (int i = 1; i <= 6; i++) //枚举下一个上方数字
    {
        // cout << link[up][edge[i]] << endl;
        if (link[up][edge[i]]) // 如果和下面的骰子不矛盾
        {
            // cout << cnt << endl;
            dfs(cnt + 1, i);
        }
    }
    return;
}
long long fast_power(long long a, long long b, long long c)
{
    long long ans = 1;
    while (b)
    {
        if (b % 2)
            ans = (ans * a) % c;
        b /= 2;
        a = (a * a) % c;
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    start();
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int remp1, remp2;
        cin >> remp1 >> remp2;
        link[remp1][remp2] = link[remp2][remp1] = 0;
    }
    for (int i = 1; i <= 6; i++)
    {
        dfs(1, i);
    }
    ans = (ans * fast_power(4, n, mod)) % mod;
    cout << ans;
    return 0;
}

第二种:dp(TLE)75分
dp[i][j]代表第i层骰子朝上的面是j时,此时的方案数

#include <bits/stdc++.h>
using namespace std;
// dp解法:http://lx.lanqiao.cn/problem.page?gpid=T2797
// 75分
const long long mod = 1e9 + 7;
long long dp[50000][7]; // dp[i][j]代表第i层j朝上时,此时有多少种方案
int op[7];              //对立面
int conflict[7][7];     //冲突
int n, m;
long long fast_power(long long a, long long b, long long c)
{
    long long ans = 1;
    while (b)
    {
        if (b % 2)
            ans = (ans * a) % c;
        b /= 2;
        a = (a * a) % c;
    }
    return ans;
}
void init() //初始化
{
    op[1] = 4;
    op[2] = 5;
    op[3] = 6;
    op[4] = 1;
    op[5] = 2;
    op[6] = 3;
    for (int i = 1; i <= 6; i++)
    {
        dp[1][i] = 1;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    init();
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int remp1, remp2;
        cin >> remp1 >> remp2;
        conflict[remp1][remp2] = conflict[remp2][remp1] = 1;
    }
    for (int i = 2; i <= n; i++) //枚举层数
    {
        for (int j = 1; j <= 6; j++) //枚举上面的骰子顶部数字
        {
            for (int k = 1; k <= 6; k++) //枚举上面骰子顶部数字
            {
                int down = op[k];
                if (conflict[j][down] == 0)
                {
                    dp[i][k] = dp[i][k] + dp[i - 1][j];
                    dp[i][k] %= mod;
                }
            }
        }
    }
    long long ans = 0;
    for (int i = 1; i <= 6; i++)
    {
        ans = ans + dp[n][i];
        ans %= mod;
    }
    ans = ans * fast_power(4, n, mod);
    ans %= mod;
    cout << ans;
    return 0;
}

第三种:矩阵快速幂(AC)100
(我不会我是菜鸡)

举报

相关推荐

0 条评论