蓝桥杯刷题笔记

奇怪的捐赠

#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
int main(){
    // 初始化变量num为1000000,代表总金额为100万元
    int num = 1000000;
    // 初始化变量cnt为0,用于记录最终划分的份数
    int cnt = 0;
    // 当num不为0时,持续进行循环,此循环的目的是将总金额按七进制拆分
    while(num) {
        // num % 7 计算出当前num在七进制下的最低位数字
        // 这个数字代表了当前7的0次方(即1元)这一份额的数量
        // 将其累加到cnt中
        cnt += num % 7;
        // num /= 7 相当于将num在七进制下右移一位
        // 也就是去掉当前七进制表示中的最低位,继续处理更高位
        num /= 7;
    }
    // 输出最终划分的份数
    cout << cnt;

    return 0;
}
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;

int main() {
    // 初始金额为100万元,单位为元
    int money = 1000000;
    // 用于记录划分的份数,初始化为0
    int cnt = 0;
    // 从7的0次方到7的7次方进行遍历,这里k表示7的幂次,从大到小遍历
    for(int k = 7; k >= 0; k--) {
        // 计算当前7的k次幂能划分出的份数,即总金额除以当前7的幂次方
        int numitems = money / pow(7, k);
        // 如果划分出的份数大于5份,按照要求最多只能取5份
        if(numitems > 5) numitems = 5;
        // 将当前划分的份数累加到总份数cnt中
        cnt += numitems;
        // 从总金额中减去当前划分所使用的金额
        money -= numitems * pow(7, k);
        // 如果总金额已经为0,说明已经全部分完,跳出循环
        if(money == 0) break;
    }
    // 输出划分的总份数
    cout << cnt;
    return 0;
}

 排序

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

// 自定义比较函数 cmp,用于降序排序
bool cmp(int a, int b) {
    return a > b;
}

int main() {
    int n;
    cin >> n;
    // 使用 vector 动态数组存储输入的整数
    vector<int> a(n);

    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }

    // 升序排序
    sort(a.begin(), a.end());

    for (int i = 0; i < n; i++) {
        cout << a[i];
        if (i < n - 1) {
            cout << " ";
        }
    }
    cout << "\n";

    // 降序排序
    sort(a.begin(), a.end(), cmp);

    for (int i = 0; i < n; i++) {
        cout << a[i];
        if (i < n - 1) {
            cout << " ";
        }
    }

    return 0;
}
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;

// 定义一个常量 maxn,用于数组的最大长度,这里设置为 1e9 + 9
const long long maxn = 5e5+9;
// 定义一个整数数组 a,用于存储输入的整数
long long a[maxn];

// 自定义比较函数 cmp,用于降序排序
bool cmp(long long a, long long b) {
    // 如果 a 大于 b,则返回 true,否则返回 false
    return a > b;
}

int main() {
    // 定义一个整数 n,用于存储输入整数的数量
    long long n;
    // 从标准输入读取整数 n
    cin >> n;

    // 循环读取 n 个整数,并存储到数组 a 中
    for (long long i = 0; i < n; i++) {
        cin >> a[i];
    }

    // 使用 sort 函数对数组 a 进行升序排序,默认情况下 sort 是升序排序
    sort(a, a + n);

    // 循环输出升序排序后的数组元素,元素之间用空格分隔
    for (long long i = 0; i < n; i++) {
        cout << a[i];
        if (i < n - 1) {
            cout << " ";
        }
    }
    // 输出换行符
    cout << "\n";

    // 使用 sort 函数和自定义比较函数 cmp 对数组 a 进行降序排序
    sort(a, a + n, cmp);

    // 循环输出降序排序后的数组元素,元素之间用空格分隔
    for (long long i = 0; i < n; i++) {
        cout << a[i];
        if (i < n - 1) {
            cout << " ";
        }
    }

    return 0;
}

4. 浓缩咖啡液【算法赛】

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;

int main(){
    // 定义变量 t,用于存储测试用例的数量
    int t;
    // 从标准输入读取测试用例的数量
    cin >> t;

    // 循环处理每个测试用例
    while(t--){
        // 定义变量 n 和 m,n 表示数组的长度,m 是一个比较值
        int n, m;
        // 从标准输入读取数组长度 n 和比较值 m
        cin >> n >> m;

        // 定义一个大小为 n 的整数向量 v,用于存储数组元素
        vector<int> v(n);
        // 循环读取 n 个整数,并将它们存入向量 v 中
        for(int i = 0; i < n; i++) {
            cin >> v[i];
        }

        // 定义两个标志变量 a 和 b,初始值都为 0
        // a 用于标记数组中是否存在小于等于 m 的元素
        // b 用于标记数组中是否存在大于等于 m 的元素
        int a = 0, b = 0;

        // 遍历向量 v 中的每个元素
        for(int i = 0; i < n; i++){
            // 如果当前元素等于 m
            if(v[i] == m){
                // 同时将 a 和 b 置为 1,表示既存在小于等于 m 的元素(就是 m 本身),也存在大于等于 m 的元素(就是 m 本身)
                a = 1;
                b = 1;
            } 
            // 如果当前元素小于 m
            else if(v[i] < m){
                // 将 a 置为 1,表示存在小于等于 m 的元素
                a = 1;
            } 
            // 如果当前元素大于 m
            else if(v[i] > m) {
                // 将 b 置为 1,表示存在大于等于 m 的元素
                b = 1;
            }
        }

        // 如果 a 和 b 都为 1,说明数组中既存在小于等于 m 的元素,又存在大于等于 m 的元素
        if(a && b) {
            // 输出 "YES" 并换行
            cout << "YES\n";
        } 
        // 否则
        else {
            // 输出 "NO" 并换行
            cout << "NO\n";
        }
    }

    return 0;
}
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

// 定义一个常量 maxn 作为数组的最大长度
const int maxn = 1010;
// 定义一个整型数组 a,用于存储输入的数字,数组大小为 maxn
int a[maxn];

int main()
{
    // 定义变量 t 用于存储测试用例的数量
    int t;
    // 从标准输入读取测试用例的数量
    cin >> t;

    // 循环处理每个测试用例,t-- 表示每次循环后 t 的值减 1,直到 t 为 0 时停止循环
    while(t--){
        // 定义变量 n 用于存储当前测试用例中数组的元素个数,m 用于存储目标值
        int n, m;
        // 从标准输入读取 n 和 m 的值
        cin >> n >> m;

        // 循环读取 n 个整数,将它们依次存入数组 a 中
        for(int i = 0; i < n; i++) {
            cin >> a[i];
        }

        // 使用 sort 函数对数组 a 进行升序排序,a 是数组起始地址,a + n 是数组结束地址的下一个位置
        sort(a, a + n);

        // 判断目标值 m 是否在排序后数组的最小值和最大值之间(包括边界值)
        if(m >= a[0] && m <= a[n - 1]) {
            // 如果满足条件,输出 "YES" 并换行
            cout << "YES\n";
        } else {
            // 如果不满足条件,输出 "NO" 并换行
            cout << "NO\n";
        }
    }
    return 0;
}

破译密码【算法赛】

#include <bits/stdc++.h>
using namespace std;
// 使用类型别名 ll 来表示 long long 类型,方便后续代码编写
using ll = long long;

// 定义一个结构体 t 来表示芯片
// 每个芯片有两个属性:l 表示解密时间,r 表示传输时间
struct t {
    ll l, r; // l 为解密时间,r 为传输时间
} a[1010];

// 自定义比较函数 cmp,用于对芯片数组进行排序
// 排序规则决定了芯片处理的顺序,以使得总时间最短
bool cmp(t a1, t a2) {
    // 比较两个芯片的解密时间和传输时间的某种组合
    // 这里的规则是根据 min(a1.l, a2.r) 和 min(a2.l, a1.r) 的大小来排序
    return min(a1.l, a2.r) < min(a2.l, a1.r);
}

// 定义全局变量
// n 表示芯片的数量
// ans 用于记录最终的最小总时间
// sum 用于记录当前累计的解密时间
ll n, ans, sum;

int main() {
    // 从标准输入读取芯片的数量 n
    cin >> n;

    // 循环读取每个芯片的解密时间,并存储在数组 a 中
    for (int i = 1; i <= n; i++) {
        cin >> a[i].l;
    }

    // 循环读取每个芯片的传输时间,并存储在数组 a 中
    for (int i = 1; i <= n; i++) {
        cin >> a[i].r;
    }

    // 使用自定义的比较函数 cmp 对芯片数组 a 进行排序
    // 排序范围是从 a[1] 到 a[n]
    sort(a + 1, a + n + 1, cmp);

    // 遍历排序后的芯片数组
    for (int i = 1; i <= n; i++) {
        // 累加当前芯片的解密时间到 sum 中
        sum += a[i].l;

        // 判断当前累计的解密时间 sum 是否大于等于之前记录的总时间 ans
        if (sum >= ans) {
            // 如果 sum 大于等于 ans,说明当前芯片的解密完成后才开始传输,更新总时间 ans
            ans = sum + a[i].r;
        } else {
            // 如果 sum 小于 ans,说明前一个芯片的传输还未完成,当前芯片的传输接着进行,更新总时间 ans
            ans = ans + a[i].r;
        }
    }

    // 输出最终的最小总时间
    cout << ans << "\n";

    return 0;
}
#include <bits/stdc++.h>
using namespace std;
// 使用typedef为long long定义一个别名ll,方便后续代码书写
typedef long long ll;

// 定义一个结构体t,用于表示芯片,每个芯片有两个属性
struct t {
    ll l, r; // l: 破译时间, r: 传输时间
} a[1010];

// Johnson算法的比较函数,用于对芯片数组进行排序,以找到最优处理顺序
bool cmp(t a1, t a2) {
    // 比较两个芯片的r和另一个芯片的l的较小值
    // 这里是Johnson算法的关键比较部分
    if (min(a1.r, a2.l) == min(a2.r, a1.l)) {
        // 当min(a1.r, a2.l)等于min(a2.r, a1.l)时
        // 按破译时间l升序排列,即a1.l较小的排在前面
        // 若两个芯片比较的关键值相等,则优先处理破译时间短的芯片
        return a1.l < a2.l;
    }
    // 若min(a1.r, a2.l)和min(a2.r, a1.l)不相等
    // 返回min(a2.r, a1.l) < min(a1.r, a2.l) 的结果
    // 这一步是Johnson算法核心比较逻辑,通过这样的比较决定芯片的排序
    // 让满足此条件的芯片a1排在a2前面,以此来优化整体处理时间
    return min(a2.r, a1.l) < min(a1.r, a2.l);
}

int main() {
    int n;
    // 从标准输入读取芯片的数量
    cin >> n;
    // 循环读取每个芯片的破译时间,并存储在数组a中
    for (int i = 1; i <= n; i++) cin >> a[i].l;
    // 循环读取每个芯片的传输时间,并存储在数组a中
    for (int i = 1; i <= n; i++) cin >> a[i].r;

    // 使用自定义的比较函数cmp对芯片数组a进行排序
    // 排序范围是从a[1]到a[n]
    // 经过排序后,芯片会按照能使总处理时间最短的顺序排列
    sort(a + 1, a + n + 1, cmp);

    // sum用于记录累计的破译时间
    // ans用于记录完成所有芯片处理的最小总时间
    ll sum = 0, ans = 0;

    // 遍历排序后的芯片数组
    for (int i = 1; i <= n; i++) {
        // 累加当前芯片的破译时间到sum中
        sum += a[i].l;
        // 计算当前芯片处理完后的总时间
        // 取ans和sum中的较大值,是因为要考虑前一个芯片传输未完成的情况
        // 然后加上当前芯片的传输时间
        // 若前一个芯片传输还未结束,当前芯片需等待,所以取较大值
        ans = max(ans, sum) + a[i].r;
    }
    // 输出完成所有芯片处理的最小总时间
    cout << ans << "\n";
    return 0;
}

插入数字【算法赛】

#include <cstdio>
#include <iostream>
// 包含 string 头文件,因为代码中使用了 std::string 类型
#include <string>
using namespace std;

int main(){
    // 定义一个字符串变量 s,用于存储从标准输入读取的字符串
    string s;
    // 从标准输入读取一个字符串,并将其存储到变量 s 中
    cin >> s;

    // 判断字符串 s 的长度是否为 1 且该字符串唯一的字符为 '0'
    if(s.size() == 1 && s[0] == '0') {
        // 如果满足条件,输出数字 9
        cout << 9;
    }

    // 计算一个值并存储在变量 sum 中
    // 计算规则是字符串 s 的长度加 1 后再乘以 9
    long long sum = (s.size() + 1) * 9;

    // 输出计算得到的 sum 值
    cout << sum;

    // 程序正常结束,返回 0
    return 0;
}
#include <iostream>
#include <string>
#include <set>

using namespace std;

int main() {
    // 定义一个字符串变量 num_str 用于存储输入的正整数
    string num_str;
    // 从标准输入读取一个正整数,并将其作为字符串存储到 num_str 中
    cin >> num_str;

    // 定义一个集合 unique_nums 用于存储插入数字后得到的不同数字
    // 集合的特性是元素唯一,可自动去重
    set<string> unique_nums;

    // 遍历可插入的数字,范围是 0 到 9
    for (int insert_num = 0; insert_num <= 9; ++insert_num) {
        // 将插入的数字转换为字符形式
        char insert_char = insert_num + '0';

        // 在数字开头插入字符
        // 若插入的数字不是 0 时才进行插入操作,避免生成以 0 开头的无效数字
        if (insert_num != 0) {
            string new_num = string(1, insert_char) + num_str;
            unique_nums.insert(new_num);
        }

        // 在数字结尾插入字符
        string new_num_end = num_str + string(1, insert_char);
        unique_nums.insert(new_num_end);

        // 在数字的相邻数字之间插入字符
        for (int i = 1; i < num_str.length(); ++i) {
            string new_num_middle = num_str.substr(0, i) + string(1, insert_char) + num_str.substr(i);
            unique_nums.insert(new_num_middle);
        }
    }

    // 输出集合中不同数字的数量,即通过插入操作能得到的不同数字的种类数
    cout << unique_nums.size() << endl;

    return 0;
}    

试题 A :跑步训练

【问题描述】

小明要做一个跑步训练。

初始时,小明充满体力,体力值计为 10000 。如果小明跑步,每分钟损耗 600 的体力。如果小明休息,每分钟增加 300 的体力。体力的损耗和增加都是均匀变化的。

小明打算跑一分钟、休息一分钟、再跑一分钟、再休息一分钟……如此循环。如果某个时刻小明的体力到达 0,他就停止锻炼。请问小明在多久后停止锻炼。

请问小明在多久后停止锻炼。为了使答案为整数,请以秒为单位输出答案。答案中只填写数,不填写单位。

【答案提交】

这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

#include <iostream>
using namespace std;

int main() {
    int n = 10000;
    int i, ans = 0;

    // 检查初始体力值是否为 0
    if (n == 0) {
        cout << ans;
        return 0;
    }

    while (true) {
        for (i = 1; i <= 60; i++) {
            n -= 10;  // 每秒钟损耗 10 的体力
            ans += 1;
            if (n <= 0) {
                cout << ans;
                return 0;  // 体力耗尽,程序结束
            }
        }
        for (i = 1; i <= 60; i++) {
            n += 5;
            ans += 1;
        }
    }

    return 0;
}    

货物摆放

#include <iostream>
using namespace std;

// 定义一个长整型变量 n,并初始化为 2021041820210418
// 这个数将作为我们后续寻找约数和因数组合的目标数
long long n = 2021041820210418;
// 定义一个长整型数组 arr,用于存储目标数 n 的约数
// 这里数组大小设置为 1000000,假设 n 的约数数量不会超过这个值
long long arr[1000000];

int main()
{
    // 定义变量 ans,用于记录满足条件的因数组合的数量,初始化为 0
    int ans = 0;
    // 定义变量 coust,用于记录数组 arr 中存储的约数的个数,初始化为 0
    int coust = 0;
    // 定义长整型变量 i,用于循环遍历寻找约数
    long long i = 0;
    // 定义长整型变量 a, b, c,用于后续三层循环中枚举因数组合
    long long a, b, c;

    // 外层循环,用于找出目标数 n 的所有约数
    // 循环条件 i * i <= n,这样只需要遍历到 n 的平方根即可,提高效率
    for (i = 1; i * i <= n; i++)
    {
        // 判断 i 是否是 n 的约数,如果 n 能被 i 整除,则 i 是 n 的约数
        if (n % i == 0)
        {
            // 将约数 i 存储到数组 arr 中,并将约数计数器 coust 加 1
            arr[coust] = i;
            coust++;
            // 判断 n 除以 i 的结果是否与 i 不相等
            // 如果不相等,说明 n / i 也是 n 的一个不同的约数,也需要存储到数组中
            if (n / i != i)
            {
                arr[coust] = (n / i);
                coust++;
            }
        }
    }

    // 三层嵌套循环,用于枚举所有可能的因数组合
    // 通过这三层循环,尝试找出所有满足 arr[a] * arr[b] * arr[c] == n 的组合
    for (a = 0; a < coust; a++)
        for (b = 0; b < coust; b++)
            for (c = 0; c < coust; c++)
            {
                // 判断当前的因数组合 arr[a]、arr[b]、arr[c] 的乘积是否等于目标数 n
                if (arr[a] * arr[b] * arr[c] == n)
                {
                    // 如果满足条件,将满足条件的因数组合数量计数器 ans 加 1
                    ans++;
                }
            }

    // 输出满足条件的因数组合的数量
    cout << ans;
    return 0;
}

小球反弹

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

int main() {
    // 初始化变量 t 为 1,t 代表长方形的个数,从 1 个长方形开始尝试
    long long t = 1;
    // 定义变量 x 为 343720,x 代表长方形水平方向的边长
    long long x = 343720;
    // 定义变量 y 为 233333,y 代表长方形垂直方向的边长
    long long y = 233333;

    // 进入一个无限循环,不断尝试不同数量的长方形
    while (1) {
        // 判断条件:当 15 乘以 t 的结果能被 x 整除,并且 17 乘以 t 的结果能被 y 整除时
        // 这里的 15 和 17 可能代表小球在水平和垂直方向上移动的相对步数
        // 当满足这个条件时,说明小球刚好回到了由 t 个长方形拼接而成的大长方形的左上角
        if ((15 * t) % x == 0 && (17 * t) % y == 0) {
            // 满足条件则跳出循环
            break;
        }
        // 如果不满足条件,将长方形的个数 t 加 1,继续尝试
        t++;
    }

    // 根据勾股定理计算小球走过的路程
    // 15 * t 是小球在水平方向上走过的总距离,17 * t 是小球在垂直方向上走过的总距离
    // sqrt(15 * 15 * t * t + 17 * 17 * t * t) 计算出小球从左下角到右上角的直线距离
    // 因为小球刚好射向角落时会按入射方向原路返回,所以总路程要乘以 2
    // 最后使用 printf 函数以保留两位小数的格式输出总路程
    printf("%.2f", 2 * sqrt(15 * 15 * t * t + 17 * 17 * t * t));

    return 0;
}

好数

#include <iostream>
using namespace std;

int main()
{
    // 定义变量 ans 用于存储从 1 到 n 中“好数”的数量,初始化为 0
    long long ans = 0;
    // 定义变量 n 用于存储输入的正整数
    long long n;
    // 从标准输入读取正整数 n
    cin >> n;

    // 外层循环,遍历从 1 到 n 的每一个整数 i
    for (long long i = 1; i <= n; i++) {
        // 将当前遍历的整数 i 赋值给 num,方便后续对其数位进行操作
        long long num = i;
        // 定义变量 digit_pos 表示数位位置,1 表示奇数位(个位、百位等),2 表示偶数位(十位、千位等),初始化为 1
        int digit_pos = 1; 
        // 定义布尔变量 is_good 用于标记当前整数 num 是否为“好数”,初始化为 true
        bool is_good = true;

        // 当 num 大于 0 时,说明还有数位需要检查,继续循环
        while (num > 0) {
            // 取出 num 的个位数字,赋值给 digit
            int digit = num % 10;
            // 判断当前数位是否为奇数位(digit_pos 对 2 取余为 1)
            if (digit_pos % 2 == 1) { 
                // 如果当前数位是奇数位,检查该数位上的数字是否为偶数
                if (digit % 2 == 0) {
                    // 如果是偶数,说明 num 不是“好数”,将 is_good 设为 false 并跳出循环
                    is_good = false;
                    break;
                }
            } else { 
                // 如果当前数位是偶数位,检查该数位上的数字是否为奇数
                if (digit % 2 == 1) {
                    // 如果是奇数,说明 num 不是“好数”,将 is_good 设为 false 并跳出循环
                    is_good = false;
                    break;
                }
            }
            // 将 num 除以 10,去掉已经检查过的个位数字,以便检查下一个数位
            num /= 10;
            // 数位位置加 1,准备检查下一个数位
            digit_pos++;
        }

        // 如果经过检查,is_good 仍为 true,说明 num 是“好数”,将 ans 加 1
        if (is_good) {
            ans++;
        }
    }

    // 输出从 1 到 n 中“好数”的数量
    cout << ans;
    return 0;
}
#include <iostream>
using namespace std;

// 函数 fun_1 用于判断一个整数的奇数位(个位、百位、万位……)上的数字是否都是奇数
bool fun_1(int a) {  
    int x = a;
    // 如果当前数字 x 不为 0,继续检查其奇数位上的数字
    if (x!= 0) {
        // 检查个位数字是否为奇数(即除以 2 的余数不为 0)
        if (x % 2!= 0) {
            // 如果是奇数,将数字 x 除以 100,跳过偶数位,继续检查下一组奇数位
            x /= 100;
            // 递归调用 fun_1 继续检查剩余的奇数位
            return fun_1(x);
        } else {
            // 如果当前奇数位上的数字是偶数,则直接返回 false
            return false;
        }
    } else {
        // 如果数字已经检查完(即 x 为 0),说明所有奇数位上的数字都是奇数,返回 true
        return true;
    }
}

// 函数 fun_2 用于判断一个整数的偶数位(十位、千位、十万位……)上的数字是否都是偶数
bool fun_2(int b) { 
    int y = b;
    // 如果当前数字 y 不为 0,继续检查其偶数位上的数字
    if (y!= 0) {
        // 先将数字 y 除以 10,使当前要检查的数位变为偶数位(因为原来的个位被跳过了)
        y /= 10;
        // 检查当前偶数位上的数字是否为偶数(即除以 2 的余数为 0)
        if (y % 2 == 0) {
            // 如果是偶数,将数字 y 再除以 10,跳过奇数位,继续检查下一组偶数位
            y /= 10;
            // 递归调用 fun_2 继续检查剩余的偶数位
            return fun_2(y);
        } else {
            // 如果当前偶数位上的数字是奇数,则直接返回 false
            return false;
        }
    } else {
        // 如果数字已经检查完(即 y 为 0),说明所有偶数位上的数字都是偶数,返回 true
        return true;
    }
}

int main()
{
    // 定义变量 N 用于存储输入的正整数,num 用于统计好数的数量,初始化为 0
    int N, num = 0;
    // 从标准输入读取正整数 N
    cin >> N;
    // 遍历从 1 到 N 的所有整数
    for (int i = 1; i <= N; i++) {
        // 如果当前整数 i 同时满足奇数位都是奇数且偶数位都是偶数(即 fun_1(i) 和 fun_2(i) 都返回 true)
        if (fun_1(i) && fun_2(i)) {
            // 则将好数的数量 num 加 1
            num++;
        }
    }
    // 输出好数的数量
    cout << num;
    return 0;
}

报数游戏

#include <iostream>
using namespace std;
// 使用宏定义 ll 作为 long long 的别名,方便后续书写
#define ll long long 

int main()
{
    // 定义一个长整型变量 n,并初始化为 202420242024
    ll n = 202420242024;
    // 使用位右移运算符(>>=)将 n 右移 1 位,相当于将 n 除以 2(对于整数来说)
    n >>= 1;
    // 将右移后得到的 n 的值乘以 24,然后输出结果
    cout << n * 24 << endl;
    return 0;
}

蛇形填数

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

// 定义一个二维数组 mp,用于存储数据,大小为 200x200
// row 用于记录当前行索引,初始化为 0
// col 用于记录当前列索引,初始化为 0
// cnt 用于给数组元素赋值的计数器,初始化为 1
int mp[200][200], row = 0, col = 0, cnt = 1; 

int main() {
    // 给数组的第一个元素 mp[0][0] 赋值为 1
    mp[0][0] = 1; 
    // 当 mp[19][19] 的值为 0 时,继续循环填充数组
    while(!mp[19][19]) { 
        // 右移操作:将当前行不变,列索引加 1,并将计数器 cnt 加 1 后赋值给该位置
        mp[row][++col] = ++cnt; 
        // 左下方移动操作:当列索引大于 0 时,不断将行索引加 1,列索引减 1,
        // 并将计数器 cnt 加 1 后赋值给相应位置
        while(col) { 
            mp[++row][--col] = ++cnt;
        }
        // 下移操作:将列索引不变,行索引加 1,并将计数器 cnt 加 1 后赋值给该位置
        mp[++row][col] = ++cnt; 
        // 右上方移动操作:当行索引大于 0 时,不断将行索引减 1,列索引加 1,
        // 并将计数器 cnt 加 1 后赋值给相应位置
        while(row) { 
            mp[--row][++col] = ++cnt;
        }
    }
    /*
    // 这部分代码用于输出整个二维数组的内容,方便调试和查看数组填充情况
    // 目前被注释掉了,运行时不会执行这部分代码
    for(int i = 0; i < 20; i++) {
        for(int j = 0; j < 20; j++) {
            cout << mp[i][j] << "  ";
        }
        cout << endl;
    }
    */
    // 输出数组中 mp[19][19] 位置的值
    cout << mp[19][19]; 
    return 0;
}

拼正方形

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

int main() {
    // 计算总方块数。7385137888721LL 是一个长整型常量,乘以 4 后再加上 10470245
    // LL 后缀用于明确表示这是一个 long long 类型的常量
    long long n = 7385137888721LL * 4 + 10470245; 

    // 从总方块数 n 开始递减,逐个检查每个数
    while (n--) {
        // 计算当前数 n 的平方根,并将结果转换为 long long 类型
        long long sqrtN = sqrt(n);

        // 检查 sqrtN 的平方是否等于 n
        // 如果相等,说明 n 是一个完全平方数
        if (sqrtN * sqrtN == n) { 
            // 若 n 是完全平方数,输出它的平方根
            cout << sqrtN << endl;
            // 找到满足条件的完全平方数后,程序结束
            return 0;
        }
    }

    // 如果没有找到满足条件的完全平方数,程序正常结束
    return 0;
}

 五子棋对弈

#include<iostream>
using namespace std;

// 定义一个 5x5 的二维数组 mp 用于表示棋盘,每个元素 0 表示未放置棋子,1 表示放置了棋子
int mp[5][5];
// 定义一个长整型变量 sum,用于统计满足特定条件(13 个棋子且无五子连珠)的棋盘状态数量
long long sum = 0;

// 检查当前棋盘状态是否满足条件的函数
void check() {
    // 定义变量 a,用于统计棋盘上放置的棋子数量
    int a = 0;
    // 遍历棋盘的每一个格子
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            // 如果当前格子放置了棋子(值为 1),则 a 加 1
            if (mp[i][j] == 1) a++;
        }
    }
    // 如果棋子数量不为 13 个,直接返回,不进行后续检查
    if (a != 13) return;

    // 此时满足棋子数量为 13 个的条件,继续检查是否有五子连珠的情况
    int count = 0;
    // 检查主对角线(左上角到右下角)上的棋子数量之和
    count += mp[0][0] + mp[1][1] + mp[2][2] + mp[3][3] + mp[4][4];
    // 如果主对角线棋子数量之和能被 5 整除,说明有五子连珠,直接返回
    if (count % 5 == 0) return; 
    count = 0;
    // 检查副对角线(右上角到左下角)上的棋子数量之和
    count += mp[0][4] + mp[1][3] + mp[2][2] + mp[3][1] + mp[4][0];
    // 如果副对角线棋子数量之和能被 5 整除,说明有五子连珠,直接返回
    if (count % 5 == 0) return; 
    count = 0;
    // 检查每一行的棋子数量之和
    for (int i = 0; i < 5; i++) {
        count += mp[i][0] + mp[i][1] + mp[i][2] + mp[i][3] + mp[i][4];
        // 如果某一行棋子数量之和能被 5 整除,说明有五子连珠,直接返回
        if (count % 5 == 0) return; 
        count = 0;
        // 检查每一列的棋子数量之和
        count += mp[0][i] + mp[1][i] + mp[2][i] + mp[3][i] + mp[4][i];
        // 如果某一列棋子数量之和能被 5 整除,说明有五子连珠,直接返回
        if (count % 5 == 0) return; 
        count = 0;
    }
    // 如果经过上述检查,没有五子连珠的情况,说明满足条件,将 sum 加 1
    sum++;
}

// 深度优先搜索函数,用于遍历所有可能的棋盘状态
void dfs(int num) { 
    // 依次由从左往右,再到从上往下的顺序遍历

    // 如果已经遍历完了 25 个格子(棋盘下满)
    if (num == 25) { 
        // 调用 check 函数检查当前棋盘状态是否满足条件
        check();
        return;
    }
    // 根据当前遍历的序号 num,换算成棋盘上的坐标
    int x = num / 5, y = num % 5; 
    // 尝试在当前位置不放置棋子(值设为 0)
    mp[x][y] = 0;
    // 继续递归遍历下一个位置
    dfs(num + 1);
    // 回溯,将当前位置的值设为 1,表示放置棋子
    mp[x][y] = 1;
    // 继续递归遍历下一个位置
    dfs(num + 1);
}

int main() {
    // 从序号 0 开始,调用 dfs 函数遍历所有可能的棋盘状态
    dfs(0); 
    // 输出满足条件的棋盘状态数量
    cout << sum; 
    return 0;
}
#include <iostream>
using namespace std;
int a[30], ans = 0;
int b[8][8];
//用来检查是否为平局
int check(){
    int pos = 0;
    for(int i = 1;i <= 5;i++){
      for(int j = 1;j <= 5;j++){
        //把25个棋子情况转化为二维的
        b[i][j] = a[++pos];
      }
    }
    //横竖交叉的情况一一进行判定
    int s3 =0,s4 = 0;
    for(int i = 1;i <= 5;i++){
      int s1 = 0,s2 = 0 ;
      for(int j = 1;j <= 5;j++){
        s1 += b[i][j];
        s2 += b[j][i];
        if(i - j==0) s3+=b[i][j];
        if(i + j == 6) s4 += b[i][j];
      }
      if(s1 == 5 || s2 == 5 || s1 == 0 || s2 == 0)  return 0;
    }
    if(s3 == 5 || s4 == 5 || s3 == 0 || s4 == 0) return 0;
    return 1;
}
int main()
{

  //使用25个状态,进行状态压缩,拿到每一次0,1的情况
  for(int i = 0;i <= (1 << 25) - 1;i++)
  {
      int s = 0;
      for(int j = 0;j < 25;j++){
          a[j + 1] = (i >> j) & 1;
          if((i>>j)&1) s++;

      }
      //小蓝13个小桥12个棋子
      if(s != 13) continue;
      if(check() ) ans++;
      
  }
  cout << ans;

  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值