2021年蓝桥杯第十二届软件赛省赛 C/C++ 大学B组 第二场 A-I

目录

  • A: 求余 (水题)
  • B:双阶乘(模拟
  • C:格点(模拟/枚举
  • D:整数分解 (闫式dp/数学)
  • E:城邦(并查集+Kruskal
  • F:特殊年份(模拟)
  • G:小平方 (模拟
  • H:完全平方数 (分解质因数)
  • I:负载均衡(小根堆 + 模拟
  • J.完美序列 待补充..

在这里插入图片描述

第二场难度比第一场低了好多
蓝桥杯题解专栏:专栏链接🚀🚀🚀

A: 求余 (水题)

在这里插入图片描述

cout << 2021 % 20 << endl;

答案 : 1

B:双阶乘(模拟

在这里插入图片描述

#include <bits/stdc++.h>using namespace std;int main () {    int ans = 1;    for (int i = 2021; i >= 1; i -= 2) {        ans = ans * i % 100000;//边乘边取余    }    cout << ans;    return 0;}

答案: 59375

C:格点(模拟/枚举

在这里插入图片描述

//输出字母三角#include <bits/stdc++.h>using namespace std;int main () {    int ans = 0;    for (int x = 1; x <= 2021; x ++) {        for (int y = 1; y <= 2021; y ++) {            if(x * y <= 2021) {                ans++;            }        }    }    cout << ans << endl;}

答案:15698

D:整数分解 (闫式dp/数学)


试了暴力5个for,跑了好久,放弃
思路一:计数DP

  • 闫式DP分析法f[i][j] += f[i - 1][j - 1]

集合划分:取i个数且总和为j的所有集合
属性:COUNT

#include <bits/stdc++.h>using namespace std;typedef long long LL;//数据太大 要开llconst int N = 5,M = 2021;LL dp[N + 1][M + 1];//数组开大一点int main () {    for (int i = 1; i <= M; i ++) {        dp[1][i] = 1;//初始化    }    for (int i = 2; i <= N; i++) {//枚举个数        for (int j = 1; j <= M; j++) {             for (int k = 1; k <= M; k++) {                    if (j > k) {//枚举所有的数的和                        dp[i][j] += dp[i - 1][j - k];                }            }         }    }    cout << dp[5][2021] << endl;    return 0;}

思路二:数学统计 + 隔板法
在这里插入图片描述

#include <bits/stdc++.h>using namespace std;typedef long long LL;//数据太大 要开llint main () {    LL ans = 1;    for (int i = 2020, j = 4; j >= 1; i --,j --) {        ans *= i / j;    }    cout << ans << endl;    return 0;}

答案:691677274345

E:城邦(并查集+Kruskal

在这里插入图片描述

#include <bits/stdc++.h>using namespace std;const int N = 2030, M = N * N / 2;//边数cn2int n = 2021, m;int p[N];//并查集struct Edge {//边    int a, b, c; //c权重        bool operator<(const Edge&t) const {            return c < t.c;        }} e[M];int find (int x) {    if(p[x] != x) {        p[x] = find(p[x]);        return p[x];    }}int get(int x, int y){  //求俩个点的权值    int res = 0;    while (x || y) { //当一个数都不为0的时候        int a = x % 10, b = y % 10;        if(a!=b) res +=a+b;        x /= 10, y /= 10;//去个位    }    return res;}int main () {    for (int i = 1; i <= n; i ++) {        p[i] = i; //初始化    }    for (int i = 1; i <= n; i ++) {        for (int j = i + 1; j <= n; j ++) {            e[m++] = {i, j, get(i, j)};        }    }    sort(e, e + m);//排序所有的边    int res = 0;    for (int i = 0; i < m; i ++) {        int a = e[i].a, b = e[i].b, c = e[i].c;        if(find(a) != find(b)) {            res += c;//加上权值            p[find(a)] = find(b);//合并集合        }    }    cout << res << endl;    return 0;}

F:特殊年份(模拟)

在这里插入图片描述

#include<bits/stdc++.h>using namespace std;string s;bool check(string s){    return s[0] == s[2] && s[3] == s[1] + 1;}int main(){    int cnt = 0;    for(int i = 0; i < 5; i ++){        cin >> s;        if(check(s)) cnt ++;    }    cout << cnt << endl;    return 0;}

G:小平方 (模拟

在这里插入图片描述

#include<bits/stdc++.h>using namespace std;int main(){    int n;    cin >> n;    int ans = 0;    for(int i = 1; i < n; i++) {        if (i * i % n * 2 < n) {//不要写i*i/2否则会出现浮点数 坑            ans ++;        }    }    cout << ans << endl;    return 0;}

H:完全平方数 (分解质因数)

在这里插入图片描述

质数&质因数知识点

分解质因数:N=p1a1 * p2a2 * p3a3 * … pnan其中pi均为质数,如果一个数是完全平方数,只要让所有的pi均为偶数次幂,开平方就能得到一个整数。

#include <bits/stdc++.h>using namespace std;typedef long long LL;int main() {	int n;	cin >> n;	LL res = 1;	for (int i = 2; i * i < n; i ++) {		if(n % i == 0) {			int s;//记录次方数			while (n % i ==0) { //继续除 并且记录指数				n /= i;				s++;	            }            if(s%2) res *= i;//如果s是奇数次幂,我们就乘上i		} 	}    if(n > 1) res *= n;    cout << res << endl;    return 0;}

I:负载均衡(小根堆 + 模拟

在这里插入图片描述

#include <bits/stdc++.h>#define x first#define y secondusing namespace std;typedef pair<int, int> PII;const int N = 200010;int n,m;int s[N];//每台计算机算力priority_queue<PII,vector<PII>,greater<PII> >q[N];//每台计算机任务//PII <结束时刻,算力>//!要小根堆int main(){    scanf("%d%d", &n, &m);    for(int i = 1; i <= n; ++ i)scanf("%d",&s[i]);//!下标从1开始    while (m -- ){        int a,b,c,d;        scanf("%d%d%d%d",&a,&b,&c,&d);        while(q[b].size()&&q[b].top().x<=a){//当堆尾的结束时刻小于当前分配时刻            s[b] += q[b].top().y;//!恢复算力 +            q[b].pop();//弹出该任务        }        if(s[b]<d)puts("-1");//当前算力无法分配        else{            q[b].push({a+c,d});//加入任务            s[b] -= d;//更新算力            printf("%dn",s[b]);//输出算力        }    }    return 0;}

J.完美序列 待补充…

【问题描述】
一个序列中取出一些元素按照原来的顺序排列成新的序列称为该序列的一
个子序列。子序列的价值为子序列中所有元素的和。
如果一个序列是单调递减的,而且除了第一个数以外的任何一个数都是上
一个数的因数,则称这个序列为一个完美序列。
一个序列中的一个子序列如果是完美序列,则称为该序列的一个完美子序
列。一个序列的最长完美子序列长度,称为该序列的完美长度。
给定正整数 n,1 至 n 的所有排列的完美长度的最大值,称为 n 阶最大完
美长度。
给定正整数 n,请求出 1 至 n 的所有排列中长度正好为 n 阶最大完美长度
的所有完美子序列的价值的和。
【输入格式】
每个评测用例包含多组询问。询问之间彼此独立。
输入的第一行包含一个整数 T,表示询问数。
接下来 T 行,每行包含一个整数 n,表示一个给定的 n。
【输出格式】
输出 T 行,依次对应每组询问的答案。
每行包含一个整数,表示对应的答案除以 1000000007 (即 109 + 7) 的余数。
【样例输入】
5
1
2
3
5
10
【样例输出】
1
3
21
140
2268000
【样例说明】
当 n = 1 时,答案显然是 1。 当 n = 2 时,全排列包括 (1, 2) 和 (2, 1),其中 (2, 1) 拥有最长的完美子序
,也就是 (2, 1) 本身,2 阶最大完美长度为 2,答案即为 2 + 1。 当 n = 3 时,全排列包括 (1, 2, 3)、(1, 3, 2)、(2, 1, 3)、(2, 3, 1)、(3, 1, 2)、
(3, 2, 1)。其中 (2, 1) 和 (3, 1) 都是最长的完美子序列,3 阶最大完美长度为 2。
序列 (1, 2, 3) 和 (1, 3, 2) 中没有长度为 2 的完美子序列。
序列 (2, 1, 3) 中有完美子序列 (2, 1),价值和为 3。
序列 (2, 3, 1) 中有完美子序列 (2, 1) 和 (3, 1),价值和为 7。
序列 (3, 1, 2) 中有完美子序列 (3, 1),价值和为 4。
序列 (3, 2, 1) 中有完美子序列 (2, 1) 和 (3, 1),价值和为 7。
答案为 3 + 7 + 4 + 7 = 21。
【评测用例规模与约定】
对于 10% 的评测用例,n ≤ 10
对于 20% 的评测用例,n ≤ 20
对于 30% 的评测用例,T ≤ 20,n ≤ 1000
对于 40% 的评测用例,T ≤ 20,n ≤ 105
对于所有评测用例,1 ≤ T ≤ 105,1 ≤ n ≤ 106。

 
友情链接
鄂ICP备19019357号-22