蓝桥杯精选习题

64 阅读3分钟

蓝桥杯精选习题

1.枚举 模拟

1.1 卡片

题目大意

不重复地用卡片拼数字 有0~9卡片各2021张,共20210张,问可以从1拼到多少?

解题思路

以模拟的思路,从1开始枚举 检查每次剩下的卡片能否拼出这个数字,有则往后+1,否则要往前回退-1. 将当前拼到的这个数,取每个位置上的数字(不断对10取模,可以依次得到个、十、百..位上的数字),并检查目前的卡片是否够,不够则无法拼成该数,退出循环,注意要-1退回到上一个数。

  • Python
a = [2021 for i in range(10)]

def check(x):
    while (x > 0):
        cur = x % 10
        if a[cur] > 0:  # 这里不能写=0 代表该个数字用完了
            a[cur] -= 1
        else:
            return 0
        x //= 10
    return 1

cnt = 1
while (check(cnt)):  # check对象为cnt 意为检查可以从1开始拼到哪一个数字
    cnt += 1
print(cnt - 1)  # 因为检查结果为目前数字不符合 应该要退回到上一个数才是答案
  • C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int num[10];
bool check(int x){
    while(x){
        int now= x%10;
        if (num[now]>0) num[now]--;
        else return false;
        x/=10;
    }
    return true;
}

int main(){
    for(int i=0;i<10;i++) num[i]=2021;
    for(int i=1;;i++){
        if (!check(i)){
            cout<<i-1<<endl;
            break;
        }
    }
    return 0;
}

1.2 数的分解

题目大意

把2019分解成3个各不相同的正整数之和,并且每个数都不包含数字2和4,共有多少种不同分解方法?注意交换顺序被视为同种方法。

解题思路

我们定义这三个各不相同的正整数为i,j,k并且必须满足i<j<k。这样就不存在交换任意俩个导致计算重复 了。 一般来说我们枚举i从 1-2019, 枚举j从 1-2019, 再枚举k从1-2019,考虑最内层的k , 当 i j确定了之后,k的值自然而然就是确定的,剩下的只要检查 i,j,k 是否满足题目说的不含 2 和 4。

  • Python
# 法1用剪枝措施
cnt = 0  
for i in range(1, 672):  # 对最小数 取到的最大值是2019/3-1=672 但包含2 故再往前推1571
    for j in range(i + 1, 1009):  # 对第二小的数 取到的最大值是(2019-1)/2-1=1008 此时第一个数最小为1
        k = 2019 - i - j
        if k > j > i and '2' not in str(i) + str(j) + str(k) and '4' not in str(i) + str(j) + str(
                k):  # 条件只能为j<k 不能为i!=j!=k这样等效于交换顺序 产生重复
            cnt += 1
print(cnt)

# 法2 不用剪枝 直接据题意简单粗暴排除
c=0
for i in range(1,2019):
    if '2' not in str(i)  and '4' not in str(i):
        for j in range(i+1,2019):
            if '2' not in str(j) and '4' not in str(j):
                k=2019-i-j
                if j<k and '2' not in str(k) and '4' not in str(k):
                   c+=1
print(c)
  • C++
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=20241211;
bool check(ll x){
    if(x<=0) return false;
    while (x)
    {
        int now=x%10;
        if(now==2|| now==4) return false;
        x/=10;
    }
    return true;
}

int main(){
    int ans=0;
    for(int i=1;i<=2019;i++){
        for(int j=i+1;j<=2019;j++){
            int k=2019-i-j;
            if(check(i)&&check(k)&&check(j)&&i<j&&j<k) ans++;  # 此处不等号不能连用
        }
    }
    cout<<ans<<endl;
    return 0;
}