【蓝桥杯历年题】2020蓝桥杯A组省赛第三场(10.18)

试题 A: 数青蛙(模拟)

在这里插入图片描述

>答案:353

个位数一位;11~19以及10的倍数两位;其余情况三位

#include <iostream>

using namespace std;

int get(int x) 
{
    if(x >= 1 && x <= 10) return 1;
    else if((x >= 11 && x <= 20) || x == 30 || x == 40 || x == 50 || x == 60 || x == 70 || x == 80 ) return 2;
    else return 3;
}

int main()
{
    int res = 0;
    res += 10 * 20;
    
    for(int i = 1;i <= 20;i ++ ) res += get(i); // 第一个数字
    for(int i = 1;i <= 20;i ++ ) res += get(i); // 第二个数字
    for(int i = 2;i <= 40;i += 2 ) res += get(i); // 第一个数字
    for(int i = 4;i <= 80;i += 4 ) res += get(i); // 第一个数字
    
    cout << res << endl;
    
    return 0;
}

试题 B: 互质(最大公约数)

在这里插入图片描述

>答案:1008

#include <iostream>

using namespace std;

int gcd(int a,int b)
{
    return b ? gcd(b,a % b) : a;
}

int main()
{
    int res = 0;
    for(int i = 1;i <= 2020;i ++ ) 
        if(gcd(i,1018) == 1) res ++;
    
    cout << res << endl;
    
    return 0;
}

试题 C: 车牌(爆搜)

在这里插入图片描述

>答案:4002750

#include <iostream>

using namespace std;

int res;

void dfs(int u,int l1,int l2) // u表示搜到第几位,
    // 从0开始,l1表示上一位是多少,l2表示上2位是多少
{
    if(u == 6) {
        res ++;
        return;
    }
    
    if(u < 3)
    {
        for(int i = 0;i <= 15;i ++ ){
            if(i == l1 && i == l2 && l1 == l2) continue;
            dfs(u + 1,i,l1);
        }
    }else{
        for(int i = 0;i <= 9;i ++ ){
            if(i == l1 && i == l2 && l1 == l2) continue;
            dfs(u + 1,i,l1);
        }
    }
}

int main()
{
    dfs(0,-1,-1);
    
    cout << res << endl;
    
    return 0;
}

试题 D: Fibonacci 集合(多路归并)

在这里插入图片描述

>答案:41269

类似题 – 62. 丑数

#include <iostream>
#include <vector>

using namespace std;

vector<long long> q;

int main()
{
    q.push_back(1);
    q.push_back(2);
    q.push_back(3);

    int i =0,j = 0,k = 0;
    while(q.size() < 2020)
    {
        long long t = min(3 * q[i] + 2,min(5 * q[j] + 3,8 * q[k] + 5));
        q.push_back(t);
        
        if(3 * q[i] + 2 == t) i ++ ;
        if(5 * q[j] + 3 == t) j ++ ;
        if(8 * q[k] + 5 == t) k ++ ;
    }
    cout << q.back() << endl;
    
    return 0;
}

试题 E: 上升子串(动态规划 | 记忆化搜索)

在这里插入图片描述在这里插入图片描述

>答案:无(无数据)

类似题 – 滑雪

#include <iostream>
#include <vector>

using namespace std;

const int N = 110;

vector<string> g;
int f[N][N]; // f[i][j]: 表示以[i,j]开头的上升子序列 
int n,m;
int dx[4] = {-1,0,1,0}, dy[4] = {0,1,0,-1};

int dfs(int x,int y) // dfs返回以[x,y]开头的上升子序列 
{
	if(f[x][y]) return f[x][y];
	f[x][y] = 1;
	
	for(int i = 0;i < 4;i ++ )
	{
		int a = x + dx[i], b = y + dy[i];
		if(a >= 0 && a < n && b >= 0 && b < m && g[a][b] > g[x][y])
		{
			f[x][y] += dfs(a,b);	
		}
	}
	return f[x][y];
}

int main()
{
	freopen("inc.txt","r",stdin);
	string s;
	while(getline(cin, s)) 	g.push_back(s);
	
	n = g.size(), m = g[0].size();


	int res = 0;
	for(int i = 0;i < n;i ++ )
		for(int j = 0;j < m;j ++ )
		{
			res += dfs(i,j);
		}
	
	cout << res << endl;
	
	return 0;
}

试题 F: 日期识别(模拟)

在这里插入图片描述在这里插入图片描述在这里插入图片描述
评测地址

#include <iostream>

using namespace std;

int main()
{
    string months[13] = {"","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
    string s;
    cin >> s;
    string month,day;
    month = s.substr(0,3);
    day += s.substr(3);
    
    for(int i = 1;i < 13;i ++)
        if(month == months[i]) cout << i << ' ';
    
    // int d = (day[0] - '0') * 10 + (day[1] - '0');
    // cout <<d;
    cout << stoi(day);
    
    return 0;
    
}

试题 G: 乘法表(进制转换)

在这里插入图片描述在这里插入图片描述在这里插入图片描述
评测地址

进制转换

#include <iostream>
#include <algorithm>

using namespace std;

int n;

char get(int x)
{
    if(x <= 9) return x + '0';
    else return x - 10 + 'A';
}

string base(int x) // 十进制转 P进制
{
    string num;
    while(x){
        num += get(x % n), x /= n;
    }
    reverse(num.begin(),num.end());
    return num;
}

int main()
{
    cin >> n;
    
    for(int i = 1;i < n;i ++ ){
        for(int j = 1;j <= i;j ++ )
        {
            cout << get(i) << "*" << get(j) << "=" << base(i * j) << ' ';
        }
        printf("\n");
    }
    
    return 0;
        
}

试题 H: 限高杆(改进spfa()算法)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
评测地址

spfa算法模板

#include <iostream>
#include <queue>
#include <vector>
#include <cstring>

using namespace std;

typedef pair<int, int> PII;

struct Node //每个点指向的下一个节点
{
    int node;
    int w;
    int no; //是否有限高杆
};

const int N = 10010;

int n, m;
vector<Node> g[N];
int d[N][3];
bool st[N][3];

void spfa()
{
    memset(d, 0x3f, sizeof d);
    d[1][0] = d[1][1] = d[1][2] = 0;

    queue<PII> q;
    q.push({1, 0}); //三种状态都加入队列
    // q.push({1, 1});
    // q.push({1, 2});

    while (q.size())
    {
        auto tt = q.front();
        q.pop();
        int t = tt.first; //当前节点
        int cnt = tt.second; //当前经过的限高杆数量
        st[t][cnt] = false;

        int num = g[t].size();
        for (int i = 0; i < num; i ++ )
        {
            int j = g[t][i].node;
            int w = g[t][i].w;
            int no = g[t][i].no;
            if (cnt + no < 3 && d[j][cnt + no] > d[t][cnt] + w) //不能超过三个限高杆
            {
                d[j][cnt + no] = d[t][cnt] + w;
                if (!st[j][cnt + no])
                {
                    q.push({j, cnt + no});
                    st[j][cnt + no] = true;
                }
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i ++ )
    {
        int a, b, c, f;
        scanf("%d%d%d%d", &a, &b, &c, &f);
        g[a].push_back({b, c, f});
        g[b].push_back({a, c, f});
    }

    spfa();

    cout << d[n][0] - min(min(d[n][0], d[n][1]), d[n][2]);

    return 0;
}


试题 I: 画中漂流(动态规划)

在这里插入图片描述在这里插入图片描述在这里插入图片描述
关键点:距离可以通过 时间和剩余体力计算出来!
题解

#include <iostream>

using namespace std;

const int N = 3010, mod = 1e9 + 7;

int d,t,m;
int f[N][N]; // f[i,j] : 花费时间为i,且剩余体力为j的方案数 答案:f[t][0],初始化f[0][m] = 1;
         // 不滑f[i - 1][j] , 滑f[i - 1][j + 1];
        // 关键点:距离可以通过 时间和剩余体力计算出来!
        // 初始距离:d, 向上游距离:m - j ,向下流距离 i - (m - j) 

int main()
{
    cin >> d >> t >> m;
    f[0][m] = 1;
    
    for(int i = 1;i <= t;i ++ )
        for(int j = 0;j <= m;j ++)
        {
            int dist = d + (m - j) -(i - (m - j));
            if(dist > 0){
                // 不滑
                f[i][j] = (f[i][j] + f[i - 1][j]) % mod;
                // 滑
                f[i][j] = (f[i][j] + f[i - 1][j + 1]) % mod;
            }
        }
    cout << f[t][0] << endl;
    
    return 0;
}

试题 J: 旅行家

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

70分代码,时间复杂度 O ( n 2 ) O(n ^ 2) O(n2),像spfa()

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>

using namespace std;

typedef long long LL;

const int N = 500010;

int n;
LL T[N],F[N];
LL rp[N];
bool st[N];

int main()
{
    cin >> n;
    for(int i = 1;i <= n;i ++ ) scanf("%lld",&T[i]);
    for(int i = 1;i <= n;i ++ ) scanf("%lld",&F[i]);
    
    memset(rp,-0x3f,sizeof rp);
    rp[1] = 0;
    queue<int> q;
    q.push(1);
    st[1] = true;
    
    
    while(q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;
        
        for(int i = t + 1;i <= n;i ++)
        {
            if(rp[t] / 2 - F[t] + T[t] * T[i] > rp[i])
            {
                rp[i]  =  rp[t] / 2 - F[t] + T[t] * T[i];
                if(!st[i])
                {
                    q.push(i);
                    st[i] = true;
                }
            }
        }
    }
    
    LL res = -1e18;
    for(int i = 1;i <= n; i ++) res = max(res,rp[i]);
    printf("%lld\n",res);
    
    return 0;
}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值