2019 蓝桥杯10届省赛
1.组队
// 比对
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
printf("%d\n", 98 + 99 + 98 + 97 + 98);
return 0;
}
2.年号字串 BYQ
#include <cstdio>
#include <iostream>
using namespace std;
char a[10];
int main() {
/*
string s;
int res = 0;
cin >> s;
for (int i = 0; i < s.size(); i ++ ) {
res = res * 26 + s[i] - 'A' + 1;
}
cout << res << endl;
*/
int n, i = 0;
scanf("%d", &n);
while (n > 0) {
a[i ++ ] = n % 26 + 'A' - 1;
n /= 26;
}
for (int i = 0; i < 5; i ++ ) {
cout << a[i] << endl;
}
return 0;
}
3.数列求值 前三项和
#include <cstdio>
#include <iostream>
using namespace std;
int f(int n) {
int a = 1, b = 1, c = 1, d;
for (int i = 1; i < n; i ++ ) {
d = (a + b + c) % 10000;
a = b;
b = c;
c = d;
}
return a;
}
int main() {
cout << f(20190324) << endl;
return 0;
}
4.数的分解
#include <cstdio>
#include <iostream>
using namespace std;
bool check(int n) {
int t = n;
while (t > 0) {
if (t % 10 == 2 || t % 10 == 4) return false;
t /= 10;
}
return true;
}
int sum;
int main() {
for (int i = 1; i <= 2019; i ++ ) {
if (check(i))
for (int j = i + 1; j <= 2019; j ++ ) {
if (check(j))
if (2019 - i - j > j && check(2019 - i - j)) sum ++ ;
}
}
printf("%d\n", sum);
return 0;
}
5.迷宫
#include<bits/stdc++.h>
using namespace std;
#define maxn 2000
string maze[maxn]= {
"01010101001011001001010110010110100100001000101010",
"00001000100000101010010000100000001001100110100101",
"01111011010010001000001101001011100011000000010000",
"01000000001010100011010000101000001010101011001011",
"00011111000000101000010010100010100000101100000000",
"11001000110101000010101100011010011010101011110111",
"00011011010101001001001010000001000101001110000000",
"10100000101000100110101010111110011000010000111010",
"00111000001010100001100010000001000101001100001001",
"11000110100001110010001001010101010101010001101000",
"00010000100100000101001010101110100010101010000101",
"11100100101001001000010000010101010100100100010100",
"00000010000000101011001111010001100000101010100011",
"10101010011100001000011000010110011110110100001000",
"10101010100001101010100101000010100000111011101001",
"10000000101100010000101100101101001011100000000100",
"10101001000000010100100001000100000100011110101001",
"00101001010101101001010100011010101101110000110101",
"11001010000100001100000010100101000001000111000010",
"00001000110000110101101000000100101001001000011101",
"10100101000101000000001110110010110101101010100001",
"00101000010000110101010000100010001001000100010101",
"10100001000110010001000010101001010101011111010010",
"00000100101000000110010100101001000001000000000010",
"11010000001001110111001001000011101001011011101000",
"00000110100010001000100000001000011101000000110011",
"10101000101000100010001111100010101001010000001000",
"10000010100101001010110000000100101010001011101000",
"00111100001000010000000110111000000001000000001011",
"10000001100111010111010001000110111010101101111000"};
bool vis[maxn][maxn];//标记
int dir[4][2]={{1,0},{0,-1},{0,1},{-1,0}};//D L R U
bool in(int x,int y)
{
return x<30&&x>=0&&y>=0&&y<50;
}
struct node
{
int x,y,d;
char pos;//存储D L R U
};
node father[maxn][maxn];//当前节点的父节点
node now,nex;//指向当前和下一个位置
void dfs(int x,int y)//递归打印
{
if(x==0&&y==0)//找到起点开始正向打印路径
return;
else
dfs(father[x][y].x,father[x][y].y);
cout<<father[x][y].pos;
}
void bfs(int x,int y)
{
queue<node> q;
now.x=x;
now.y=y;
now.d=0;
q.push(now);
vis[x][y]=true;
while(!q.empty())
{
now=q.front();
q.pop();
for(int i=0;i<4;i++)//走下左右上按字典序的四个方向
{
int tx=now.x+dir[i][0];
int ty=now.y+dir[i][1];
if(in(tx,ty)&&!vis[tx][ty]&&maze[tx][ty]!='1')//判断是否超出范围,是否用过,是否为1
{
vis[tx][ty]=true;//标记为用过
nex.x=tx;
nex.y=ty;
nex.d=now.d+1;
q.push(nex);//压入队列
father[tx][ty].x=now.x;//存储父节点坐标
father[tx][ty].y=now.y;
if(i==0)//存储路径
father[tx][ty].pos='D';
else if(i==1)
father[tx][ty].pos='L';
else if(i==2)
father[tx][ty].pos='R';
else if(i==3)
father[tx][ty].pos='U';
}
}
}
}
int main()
{
bfs(0,0);
dfs(29,49);//打印路径
return 0;
}
6.特别数的和
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
int n, sum = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) {
int t = i;
bool flag = false;
while (t > 0) {
if (t % 10 == 2 || t % 10 == 0 || t % 10 == 1 || t % 10 == 9) {
flag = true;
break;
}
t /= 10;
}
if (flag) sum += i;
}
printf("%d\n", sum);
return 0;
}
7.完全二叉树的权值
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int a[N];
int n;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
LL maxs = -1e18;
int depth = 0;
for (int d = 1, i = 1; i <= n; i *= 2, d ++ ) {
LL s = 0;
for (int j = i; j < i + (1 << d - 1) && j <= n; j ++ )
s += a[j];
if (s > maxs) {
maxs = s;
depth = d;
}
}
printf("%d\n", depth);
return 0;
}
8.等差数列
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n, d;
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
int main() {
scanf("%d", &n);
for (int i = 0; i <= n - 1; i ++ ) scanf("%d", &a[i]);
sort(a, a + n);
for (int i = 1; i <= n - 1; i ++ ) d = gcd(d, a[i] - a[0]);
if (d == 0) {
printf("%d\n", n);
} else {
printf("%d\n", (a[n - 1] - a[0]) / d + 1);
}
return 0;
}
9.后缀表达式
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 2e5 + 10;
int main() {
ios::sync_with_stdio(false);
int n, m;
cin >> n >> m;
vector<int>a(n + m + 1);
for (int i = 0; i < n + m + 1; i++) cin >> a[i];
if (!m) cout << accumulate(a.begin(), a.end(), 0ll) << '\n';
else {
sort(a.begin(), a.end());
ll ans = -a.front() + a.back();
for (int i = 1; i < n + m; i++) ans += abs(a[i]);
cout << ans << '\n';
}
return 0;
}
10.灵能传输
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
signed main() {
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<ll>s(n + 1);
for (int i = 0; i < n; i++) {
int x;
cin >> x;
s[i + 1] = s[i] + x;
}
ll s0 = s[0], sn = s[n];
if (s0 > sn) swap(s0, sn);
sort(s.begin(), s.end());
for (int i = 0; i <= n; i++) if (s[i] == s0) {
s0 = i;
break;
}
for (int i = n; i >= 0; i--) if (s[i] == sn) {
sn = i;
break;
}
vector<ll>a(n + 1);
vector<bool>v(n + 1);
int l = 0, r = n;
for (int i = s0; i >= 0; i -= 2)
a[l++] = s[i], v[i] = true;
for (int i = sn; i <= n; i += 2)
a[r--] = s[i], v[i] = true;
for (int i = 0; i <= n; i++)
if (!v[i]) a[l++] = s[i];
ll ans = 0;
for (int i = 1; i <= n; i++) ans = max(ans, abs(a[i] - a[i - 1]));
cout << ans << '\n';
}
return 0;
}
2020 蓝桥杯11届省赛
1.门牌制作
#include <iostream>
#include <cstdio>
using namespace std;
int sum;
int main() {
for (int i = 1; i <= 2020; i ++ ) {
int t = i;
while (t > 0) {
if (t % 10 == 2) {
sum ++ ;
}
t /= 10;
}
}
printf("%d\n", sum);
return 0;
}
2.既约分数
#include <iostream>
#include <cstdio>
using namespace std;
int sum;
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
// int gcd(int a, int b) {if (b == 0) return a; else return gcd(b, a % b);}
}
int main() {
for (int i = 1; i <= 2020; i ++ ) {
for (int j = 1; j <= 2020; j ++ ) {
if (gcd(i, j) == 1) sum ++ ;
}
}
printf("%d\n", sum);
return 0;
}
3.蛇形填数 找规律 (n - 1) * (n - 1) + n * n
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
cout << 19 * 19 + 20 * 20 << endl;
return 0;
}
4.跑步锻炼 模拟构造 日期
#include <iostream>
#include <cstdio>
using namespace std;
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool valid(int date) {
int year = date / 10000;
int month = date % 10000 / 100;
int day = date % 100;
if (month == 0 || month > 12) return false;
if (day == 0 || month != 2 && day > days[month]) return false;
if (month == 2) {
int leap = year % 100 != 0 && year % 4 == 0 || year % 400 == 0;
if (day > 28 + leap) return false;
}
return true;
}
int sum, ans; // 正确合法记录的总日子sum 求星期一 %7 == 3需要加 总答案ans
int main() {
for (int i = 20000101; i <= 20201001; i ++ ) {
if (valid(i)){
sum ++ ;
ans ++ ;
if (sum % 7 == 3 || i % 100 == 1) ans ++ ;
}
}
printf("%d\n", ans);
return 0;
}
5.七段码
/*
题目大意
小蓝要用七段码数码管来表示一种特殊的文字。
图片描述
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。
小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。
请问,小蓝可以用七段码数码管表达多少种不同的字符?
解题思路
我们可以把每个二极管看成一条边,并把相邻的边相连,那么这样题目就可以转换为:
有多少种选边方案,使得选出来的边构成的图只有一个联通快。
于是现在只要枚举选边方案,再判断联通块的个数是否为 1 即可。
枚举选边方案可以采用状压(当然直接 dfs 搜索也行):用二进制 1、0 分别表示二进制位所对应的边是选还是不选,复杂度为 2^7。
求联通块的个数可以采用 bfs(也可以采用并查集等方法):从任意一个选中的边出发将所有能到达的选中的边全部打上标记;若标记覆盖了所有选中的边则联通快只有一个(满足条件),反之不止一个联通块(不满足条件)。
最后的答案为 80。
*/
#include<bits/stdc++.h>
using namespace std;
int ans , g[7][7] , vis[7] , flag[7];
void bfs(int x){
queue<int>que;
que.push(x);
vis[x] = true;
while(!que.empty()){
int u = que.front();
que.pop();
for(int i = 0 ; i <= 6 ; i ++){
if(g[u][i] && flag[i] && !vis[i]){
vis[i] = true;
que.push(i);
}
}
}
}
bool check(int x){
for(int i = 0 ; i <= 6 ; i ++) flag[i] = vis[i] = false;
int cnt = 0;
for(int i = 6 ; ~i ; i --) if(x >> i & 1) flag[i] = true;
for(int i = 0 ; i <= 6 ; i ++){
if(flag[i] && !vis[i]){
bfs(i);
cnt ++ ;
}
}
return cnt == 1;
}
signed main()
{
g[0][1] = g[0][5] = 1;
g[1][0] = g[1][2] = g[1][6] = 1;
g[2][1] = g[2][3] = g[2][6] = 1;
g[3][2] = g[3][4] = 1;
g[4][3] = g[4][5] = g[4][6] = 1;
g[5][0] = g[5][4] = g[5][6] = 1;
g[6][1] = g[6][2] = g[6][4] = g[6][5] = 1;
for(int i = 0 ; i < (1 << 7) ; i ++){
if(check(i)) {
ans ++ ;
}
}
cout << ans << '\n';
return 0;
}
6.成绩统计
#include <iostream>
#include <cstdio>
using namespace std;
int n, t, x, y, a, b;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) {
scanf("%d", &t);
if (t >= 60) {
x ++ ;
if (t >= 85) {
y ++ ;
}
}
}
int a = x * 100.0 / n + 0.5, b = y * 100.0 / n + 0.5;
printf("%d%%\n%d%%", a, b);
return 0;
}
7.回文日期 大模拟 构造
#include <iostream>
#include <cstdio>
using namespace std;
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool valid(int date) {
int year = date / 10000;
int month = date % 10000 / 100;
int day = date % 100;
if (month == 0 || month > 12) return false;
if (day == 0 || month != 2 && day > days[month]) return false;
if (month == 2) {
int leap = year % 100 != 0 && year % 4 == 0 || year % 400 == 0;
if (day > 28 + leap) return false;
}
return true;
}
bool check1(int date) {
int d1 = date / 10000, d2 = date % 10000, x = 0;
for (int i = 0; i < 4; i ++ ) {
x = x * 10 + d2 % 10, d2 /= 10; // 1234 -> 4321
}
return d1 == x;
}
bool check2(int date) {
int month = date % 10000 / 100, day = date % 100;
return month == day;
}
int n, ans1, ans2;
int main() {
scanf("%d", &n);
for (int i = n + 1; i <= 99999999; i ++ ) {
if (check1(i) && valid(i)) {
ans1 = i;
break;
}
}
for (int i = n + 1; i <= 99999999; i ++ ) {
if (check2(i) && check1(i) && valid(i)) {
ans2 = i;
break;
}
}
printf("%d\n%d\n", ans1, ans2);
return 0;
}
8.子串分值和
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
char s[N];
int suf[N] , last[30];
signed main()
{
cin >> s + 1;
int n = strlen(s + 1) , ans = 0;
for(int j = 0 ; j <= 25 ; j ++) last[j] = n + 1;
for(int i = n ; i >= 1 ; i --){
suf[i] = last[s[i] - 'a'];
last[s[i] - 'a'] = i;
}
for(int i = 1 ; i <= n ; i ++){
ans += i * (suf[i] - i);
}
cout << ans << '\n';
return 0;
}
9.平面切分
#include<bits/stdc++.h>
using namespace std;
int n , ans = 1;
set<pair<int , int>>line;
int calc(int a , int b){
set<pair<double , double>>node;
for(auto i : line){
int A = i.first , B = i.second;
if(A == a) continue ;
double x = 1.0 * (B - b) / (a - A);
double y = x * a + b;
node.insert(make_pair(x , y));
}
return node.size() + 1;
}
signed main()
{
cin >> n;
for(int i = 1 ; i <= n ; i ++) {
int a , b;
cin >> a >> b;
if(line.find(make_pair(a , b)) != line.end()) continue;
ans += calc(a , b);
line.insert(make_pair(a , b));
}
cout << ans << '\n';
return 0;
}
10.字串排序
#include<bits/stdc++.h>
using namespace std;
int V , len , now , cnt[27] , sum[27];
int get_max(int len){
return ((len - (len / 26 + 1)) * (len / 26 + 1) * (len % 26) + (26 - len % 26) * (len / 26) * (len - len / 26)) / 2;
}
bool check(int x , int n){
memset(cnt , 0 , sizeof(cnt));
int add1 = 0 , add2 = 0;
for(int j = 26 ; j >= x + 1 ; j --) add1 += sum[j];
sum[x] ++ ;
for(int L = 1 ; L <= n ; L ++){
int ma = -1 , pos = 0 , num = 0;
for(int j = 26 ; j >= 1 ; j --){
if(L - 1 - cnt[j] + num > ma){
ma = L - 1 - cnt[j] + num;
pos = j;
}
num += sum[j];
}
add2 += ma , cnt[pos] ++;
}
if(now + add1 + add2 >= V) {
now += add1;
return true;
}
else {
sum[x] -- ;
return false;
}
}
signed main()
{
string ans = "";
cin >> V;
for(int i = 1 ; ; i ++) {
if(get_max(i) >= V){
len = i;
break ;
}
}
for(int i = 1 ; i <= len ; i ++){
for(int j = 1 ; j <= 26 ; j ++){
if(check(j , len - i)){
ans += char(j + 'a' - 1);
break ;
}
}
}
cout << ans << '\n';
return 0;
}
2021 蓝桥杯12届省赛
1.空间
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
printf("%d\n", 256 * 1024 * 1024 / (32 / 8));
return 0;
}
2.卡片
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
int a[10], temp;
for (int i = 0; i <= 9; i ++ ) {
a[i] = 2021;
}
for (int i = 1; ; i ++ ) {
int t = i;
bool flag = true;
while (t > 0) {
if (a[t % 10] > 0) {
a[t % 10] -- ;
}
else {
flag = false;
break;
}
t /= 10;
}
if (flag == false) {
temp = i;
break;
}
}
printf("%d\n", temp - 1);
return 0;
}
3.直线
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 500010;
struct node{
double k, b;
bool operator<(const node& t)const {
if (k != t.k) return k < t.k;
return b < t.b;
}
}line[N];
// k = (y2 - y1) / (x2 - x1)
// b = m
int cnt, sum;
int main() {
for (int x1 = 0; x1 < 20; x1 ++ ) {
for (int y1 = 0; y1 < 21; y1 ++ ) {
for (int x2 = 0; x2 < 20; x2 ++ ) {
for (int y2 = 0; y2 < 21; y2 ++ ) {
if (x1 != x2) {
double k = (double)(y2 - y1) / (x2 - x1);
double b = k * x1 - y1;
line[cnt ++ ] = {k, b};
}
}
}
}
}
sort(line, line + cnt);
for (int i = 0; i + 1 < cnt; i ++ ) {
if (fabs(line[i + 1].k - line[i].k) > 1e-8 || fabs(line[i + 1].b - line[i].b) > 1e-8)
sum ++ ;
}
printf("%d\n", sum + 1 + 20);
return 0;
}
4.货物摆放
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
int ans;
int main() {
vector<long long> v;
long long n = 2021041820210418;
for (long long i = 1; i * i <= n; i ++ ) {
if (n % i == 0) {
v.push_back(i);
if (n / i != i) v.push_back(n / i); // 把自身,另一半约数,也放进去
}
}
for (long long i : v) {
for (long long j : v) {
for (long long k : v) {
if (i * j * k == n) ans ++ ;
}
}
}
printf("%d\n", ans);
return 0;
}
5.路径 最短路算法1-2021 21
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 2200, M = N * 50;
int n;
int h[N], e[M], w[M], ne[M], idx;
int q[N], dist[N];
bool st[N];
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
void spfa() {
int hh = 0, tt = 0;
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
q[tt ++ ] = 1;
st[1] = true;
while (hh != tt) {
int t = q[hh ++ ];
if (hh == N) hh = 0;
st[t] = false;
for (int i = h[t]; i != -1; i = ne[i]) {
int j = e[i];
if (dist[j] > dist[t] + w[i]) {
dist[j] = dist[t] + w[i];
if (!st[j]) {
q[tt ++ ] = j;
if (tt == N) tt = 0;
st[j] = true;
}
}
}
}
}
int main() {
n = 2021;
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++ )
for (int j = max(1, i - 21); j <= min(n, i + 21); j ++ ) {
int d = gcd(i, j);
add(i, j, i * j / d);
}
spfa();
printf("%d\n", dist[n]);
return 0;
}
6.时间显示
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
long long t;
scanf("%lld", &t);
t /= 1000;
t %= (24 * 3600);
int h = t / 3600;
int m = t % 3600 / 60;
int s = t % 60;
printf("%02d:%02d:%02d", h, m, s);
return 0;
}
7.砝码称重 DP
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
LL dp[N], w[105];
int main() {
LL n;
scanf("%lld", &n);
for (LL i = 1; i <= n; i ++ ) {
scanf("%lld", &w[i]);
}
memset(dp, 0, sizeof dp);
dp[0] = 1;
for (LL i = 1; i <= n; i ++ ) {
for (LL j = 100000; j >= w[i]; j -- ) {
dp[j] = max(dp[j], dp[j - w[i]]);
}
}
for (LL i = 1; i <= n; i ++ ) {
LL siz = 100000 - w[i];
for (LL j = 1; j <= siz; j ++ ) {
dp[j] = max(dp[j], dp[j + w[i]]);
}
}
LL ans = 0;
for (LL i = 1; i <= 100000; i ++ ) {
ans += dp[i];
}
printf("%lld\n", ans);
return 0;
}
8.杨辉三角 int long long
#include <cstdio>
#include <iostream>
using namespace std;
long long n;
long long C(long a, long long b) {
long long res = 1;
for (long long i = a, j = 1; j <= b; i -- , j ++ ) {
res = res * i / j;
if (res > n) return res;
}
return res;
}
int main() {
scanf("%lld", &n);
for (long long k = 16; ~k; k -- ) {
long long l = 2 * k, r = max(n, l), res = -1;
while (l <= r) {
long long mid = (l + r) / 2;
if (C(mid, k) >= n) res = mid, r = mid - 1;
else l = mid + 1;
}
if (C(res, k) == n) {
printf("%lld\n", (res + 1) * res / 2 + k + 1);
return 0;
}
}
return 0;
}
9.双向排序
#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 100010;
int n, m;
PII stk[N];
int ans[N];
int main() {
scanf("%d %d", &n, &m);
int top = 0;
while (m -- ) {
int p, q;
scanf("%d %d", &p, &q);
if (!p) {
while (top && stk[top].x == 0)
q = max(q, stk[top--].y);
while (top >= 2 && stk[top - 1].y <= q)
top -= 2;
stk[++top] = {0, q};
} else if (top) {
while (top && stk[top].x == 1)
q = min(q, stk[top--].y);
while (top >= 2 && stk[top - 1].y >= q)
top -= 2;
stk[++top] = {1, q};
}
}
int k = n, l = 1, r = n;
for (int i = 1; i <= top; i ++ ) {
if (stk[i].x == 0)
while (r > stk[i].y && l <= r)
ans[r--] = k--;
else
while (l < stk[i].y && l <= r)
ans[l++] = k--;
if (l > r)
break;
}
if (top % 2) {
while (l <= r)
ans[l++] = k--;
}
else {
while (l <= r)
ans[r--] = k--;
}
for (int i = 1; i <= n; i ++ ) {
printf("%d ", ans[i]);
}
return 0;
}
10.括号序列
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 5010, MOD = 1e9 + 7;
int n;
char str[N];
LL f[N][N];
LL work() {
memset(f, 0, sizeof f);
f[0][0] = 1;
for (int i = 1; i <= n; i ++ ) {
if (str[i] == '(') {
for (int j = 1; j <= n; j ++ ) {
f[i][j] = f[i - 1][j - 1];
}
} else {
f[i][0] = (f[i - 1][0] + f[i - 1][1]) % MOD;
for (int j = 1; j <= n; j ++ )
f[i][j] = (f[i - 1][j + 1] + f[i][j - 1]) % MOD;
}
}
for (int i = 0; i <= n; i ++ )
if (f[n][i])
return f[n][i];
return -1;
}
int main() {
scanf("%s", str + 1);
n = strlen(str + 1);
LL l = work();
reverse(str + 1, str + n + 1);
for (int i = 1; i <= n; i ++ ) {
if (str[i] == '(') str[i] = ')';
else str[i] = '(';
}
LL r = work();
printf("%lld\n", l * r % MOD);
return 0;
}
2021 蓝桥杯12届国赛 很难
1.带宽
200mbps = 25MB/s
2.纯质数 线性筛质数
#include <iostream>
using namespace std;
const int N = 20210605;
int prime[N];
bool st[N];
void get_Prime(){
int cnt=0;
for(int i=2;i<=N;i++){
if(!st[i]) prime[cnt++]=i;
for(int j=0;prime[j]<=N/i;j++){
st[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
int main()
{
int num=0;
get_Prime();
for(int i=2;i<=20210605;i++){
if(!st[i]){
int x=i,flag=1;
while(x){
if(x%10==2||x%10==3||x%10==5||x%10==7){
x/=10;
}else{
flag=0;
break;
}
}
if(flag==1) num++;
}
}
cout << num << endl;
return 0;
}
3.完全日期 模拟 构造 977
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool valid(int date) {
int year = date / 10000;
int month = date % 10000 / 100;
int day = date % 100;
if (month == 0 || month > 12) return false;
if (day == 0 || month != 2 && day > days[month]) return false;
if (month == 2) {
int leap = year % 100 != 0 && year % 4 == 0 || year % 400 == 0;
if (day > 28 + leap) return false;
}
return true;
}
int add(int n) {
int sum = 0;
int t = n;
while (t > 0) {
sum += t % 10;
t /= 10;
}
return sum;
}
int ans;
int main() {
for (int i = 20010101; i <= 20211231; i ++ ) {
if (valid(i)) {
int x = i / 10000, y = i % 10000 / 100, z = i % 100;
int s = add(x) + add(y) + add(z);
if ((int)sqrt(s) * (int)sqrt(s) == s) ans ++ ;
}
}
printf("%d\n", ans);
return 0;
}
4.最小权值 二叉树
/**2597854139*/
#include <bits/stdc++.h>
using namespace std;
const int maxn=2022;
#define ll long long
ll f[maxn],w[maxn];
void get(int c,int x,int l,int r){
if(x>2021)return ;
if(l<=2021){
f[c]++;
get(c,l,l*2,l*2+1);
}
if(r<=2021){
f[c]++;
get(c,r,r*2,r*2+1);
}
}
int main(){
for(int i=1;i<=2021;i++){
f[i]=0,w[i]=0;
}
for(int i=1;i<=2021;i++){
get(i,i,i*2,i*2+1);//当前结点 左结点 右结点
}
for(int i=2021;i>=1;i--){
if(2*i>2021 && 2*i+1>2021){
w[i]=0;
continue;
}
w[i]=1;
int mark=0;
if(i*2<=2021){
//左结点
w[i]+=2*w[i*2];
mark++;
}
if(i*2+1<=2021){
//右结点
w[i]+=3*w[i*2+1];
mark++;
}
if(mark==2){
w[i]+=(f[i*2]*f[i*2])*f[i*2+1];
}
}
cout<<w[1]<<endl;
return 0;
}
5.大写
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
string s;
getline(cin, s);
for (int i = 0; i < s.size(); i ++ ) {
if (s[i] >= 'a' && s[i] <= 'z') {
s[i] -= 32;
}
}
cout << s << endl;
return 0;
}
6.#F 123
c++语言 二分
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
ll cal(ll x){
return (x+1)*x/2;
}
//1.注意一定全部开ll
/* 一个数列 1 1 2 1 2 3 1 2 3 4 */
ll a[1500000];ll num[1500000];
//数组是不会改变的,打表预处理,结束条件是下标大于1e12
int main(int argc, char** argv) {
ll t,l,r;
cin>>t;
ll sum=0;int ed=0;
num[0]=0;
for(int i=1;;i++){
sum+=i;
if(sum>1e12){
ed=i-1;
break;
}
a[i]=sum;//a[i]是每个序列结尾的数字的位置,例如1234这个序列4的下标在序列下是10
//你可以写出来看一看,用这个结尾位置我们就好定位两个数字之间有多少个序列了
num[i]=num[i-1]+a[i];//类似前缀和的方法,方便计算,可以把下面那些注释掉的打开看看
}
// for(int i=1;i<ed;i++){
// cout<<a[i]<<' '<<num[i]<<endl;
// }
ll pos,pos1,tmp,tmp1;
while(t--){
cin>>l>>r;
pos=0,pos1=0;
pos=lower_bound(a,a+ed,l)-a;//lower_bound函数返回第一个大于等于该数字的下标
pos1=lower_bound(a,a+ed,r)-a;
//cout<<pos<<' '<<pos1<<endl;
ll ans=num[pos1-1]-num[pos-1];//虽然前缀和的是r - l-1,不过为了简便计算,我们最后一列可以不算,用求和的方式算出来,即下面的cal(tmp1)而前面多出来的部分是cal(tmp)
//cout<<ans<<endl;
tmp=l-a[pos-1]-1;//多减一个1,因为l这一位是要的
tmp1=r-a[pos1-1];
//cout<<tmp<<' '<<tmp1<<endl;
ans+=cal(tmp1);
ans-=cal(tmp);
printf("%lld\n",ans);//当输入输出很多的时候用scanf,printf。
}
return 0;
}
java 满分
import java.io.*;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) { new Main().run(); }
int N = (int)Math.sqrt(2E12) + 1;
long[] row = new long[N + 1], col = new long[N + 1];
void run() {
InputReader in = new InputReader(System.in);
PrintWriter out = new PrintWriter(System.out);
for (int i = 1; i <= N; i++) {
row[i] = i + row[i - 1];
col[i] = col[i - 1] + row[i];
}
int T = in.readInt();
long l, r;
while (T-- > 0) {
l = in.readLong();
r = in.readLong();
out.println(sum(r) - sum(l - 1));
}
out.flush();
}
long sum(long r) {
int k = lowerBound(r);
return r == row[k] ? col[k] : col[k - 1] + row[(int)(r - row[k - 1])];
}
int lowerBound(long k) {
int offset = 0, length = N + 1;
while (length > 0) {
int half = length >> 1;
if (k > row[offset + half]) {
offset += half + 1;
length -= half + 1;
} else length = half;
}
return offset;
}
class InputReader {
BufferedReader reader;
StringTokenizer token;
InputReader(InputStream in) {
this.reader = new BufferedReader(new InputStreamReader(in));
}
String read() {
while (token == null || !token.hasMoreTokens()) {
try {
token = new StringTokenizer(reader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return token.nextToken();
}
int readInt() { return Integer.parseInt(read()); }
long readLong() { return Long.parseLong(read()); }
}
}
7.异或变换
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int p=2,N=11000;
int c[N],n;
ll t;
char s[N];
int res[N];
int main()
{
cin>>n>>t;
for(int i=0;i<=n;i++){
c[i]=(t&i)==i;
}
cin>>s+1;
for(int i=1;i<=n;i++){
int v=s[i]-'0';
for(int j=0;j+i<=n;j++){
res[i+j]^=c[j]*v;
}
}
for(int i=1;i<=n;i++) {
cout<<res[i];
}
}
8.二进制问题
#include<iostream>
#include<cstring>
using namespace std;
int bits[70];
long long dp[70][70][2];
long long n, k;
long long dfs(int pos, long long count, int limit) {
if (pos == -1) return count == k;
if (!limit && dp[pos][count][limit] != -1) return dp[pos][count][limit];
int up = limit ? bits[pos] : 1;
long long ans = 0;
for (int i = 0; i <= up; ++i) {
ans += dfs(pos - 1, count + (i == 1), i == up && limit);
}
if (!limit) dp[pos][count][limit] = ans;
return ans;
}
int main() {
cin >> n >> k;
int len = 0;
memset(dp, -1, sizeof(dp));
while (n) {
bits[len++] = n & 1;
n >>= 1;
}
cout << dfs(len - 1, 0, 1) << endl;
return 0;
}
9.翻转括号序列
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
#define mid ((l + r) >> 1)
#define ls (t << 1)
#define rs (t << 1 | 1)
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
struct Node{int mx , mi , sw , add;}tr[maxn << 2];
int a[maxn];
char s[maxn];
int n , m;
template <typename T>
void read(T & x){ x = 0;T f = 1;char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;
ch = getchar();}while (isdigit(ch)){x = x * 10 + (ch ^ 48);ch = getchar();}x *= f;}
template <typename T>
void write(T x){if(x < 0){putchar('-');x = -x;}if (x > 9)write(x / 10);putchar(x % 10 + '0');}
void pushup (int t){
tr[t].mx = max(tr[ls].mx , tr[rs].mx);
tr[t].mi = min(tr[ls].mi , tr[rs].mi);
}
void build (int t , int l , int r){
if (l == r){
tr[t].mx = tr[t].mi = a[l];
return ;
}
build(ls , l , mid);
build(rs , mid + 1 , r);
pushup(t);
}
void D_sw (int t){
int mx = tr[t].mx , mi = tr[t].mi;
tr[t].mx = -mi; tr[t].mi = -mx;
tr[t].sw ^= 1;
tr[t].add *= -1;
}
void D_add (int t , int c){
tr[t].mi += c;
tr[t].mx += c;
tr[t].add += c;
}
void pushdown (int t){
if (tr[t].sw){
D_sw(ls);
D_sw(rs);
tr[t].sw = 0;
}
if (tr[t].add){
D_add(ls,tr[t].add);
D_add(rs,tr[t].add);
tr[t].add = 0;
}
}
void Swap (int t , int l , int r , int L , int R){
if (L <= l && r <= R){
D_sw(t);
return ;
}
pushdown(t);
if (L <= mid) Swap(ls , l , mid , L , R);
if (R > mid) Swap(rs , mid + 1 , r , L , R);
pushup(t);
return ;
}
void add (int t , int l , int r , int L , int R , int c){
if (L <= l && r <= R){
D_add(t , c);
return ;
}
pushdown(t);
if (L <= mid) add(ls , l , mid , L , R , c);
if (R > mid) add(rs , mid + 1 , r , L , R , c);
pushup(t);
return ;
}
// 单点查值
int ask1 (int t , int l , int r , int p){
if (l == r) return tr[t].mx;
pushdown(t);
if (p <= mid) return ask1(ls , l , mid , p);
return ask1(rs , mid + 1 , r , p);
}
// 找[p,n]中离p最近的一个小于c的点
int ask2 (int t , int l , int r , int p , int c){
// -1 代表该区域没有 < c 的数
if (l == r) return l;
pushdown(t);
// 优先往左走,再考虑什么情况下可以往左走
// PS:这么走,答案只是"可能"存在
int res = -1;
if (tr[ls].mi < c && p <= mid)
res = ask2(ls , l , mid , p , c);
if (res != -1) return res;
// 程序能执行到这里代表左边不存在答案了.只能往右走了
if (tr[rs].mi < c)
res = ask2(rs , mid + 1 , r , p , c);
return res;
}
// 找[1,p]中离p最近的小于c的点
int ask3 (int t , int l , int r , int p , int c){
if (l == r) return l;
pushdown(t);
int res = -1;
if (tr[rs].mi < c && p > mid)
res = ask3(rs , mid + 1 , r , p , c);
if (res != -1) return res;
if (tr[ls].mi < c) res = ask3(ls , l , mid , p , c);
return res;
}
int pre[maxn];
void modify (int x){
if (x == 0) return ;
int v = ask1(1 , 1 , n , x);
Swap(1 , 1 , n , 1 , x);
if (x != n) add(1 , 1 , n , x + 1 , n , -2 * v);
}
int main()
{
read(n); read(m);
scanf("%s" , s + 1);
for (int i = 1 ; i <= n ; i++){
if (s[i] == '(') a[i] = a[i - 1] + 1;
else a[i] = a[i - 1] - 1;
}
build(1 , 1 , n);
for (int i = 1 ; i <= m ; i++){
int op , x , y; read(op);
if (op == 1){
read(x);read(y);
modify(x - 1);
modify(y);
}else {
read(x);
int v;
if (x == 1) v = 0;
else v = ask1(1 , 1 , n , x - 1);
int p = ask2(1 , 1 , n , x , v);
if (p == -1) p = n + 1;
int r = ask3(1 , 1 , n , p - 1 , v + 1);
if (r == -1) r = 0;
printf("%d\n" , (r <= x ? 0 : r));
}
}
return 0;
}
10.异或三角
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t,n;
int f[31][2][2][2][2][2][2];
int a[31],k;
int dfs(int pos,int op1,int op2,int op3,int c1,int c2,int big)
{
if(!pos) {
return big&&c1&&c2;
}
if(~f[pos][op1][op2][op3][c1][c2][big]) {
return f[pos][op1][op2][op3][c1][c2][big];
}
int up1=op1?a[pos]:1;
int up2=op2?a[pos]:1;
int up3=op3?a[pos]:1;
int res=0;
res+=dfs(pos-1,op1&&(!up1),op2&&(!up2),op3&&(!up3),c1,c2,big);
if(up1&&up3)res+=dfs(pos-1,op1,op2&&(up2==0),op3,c1,1,big);
if(up2&&up3)res+=dfs(pos-1,op1&&(up1==0),op2,op3,1,c2,big);
if(c1&&c2) res+=dfs(pos-1,op1,op2,op3&&(!up3),1,1,1);
return f[pos][op1][op2][op3][c1][c2][big]=res;
}
int solve(int x)
{
k=0;
memset(f,-1,sizeof f);
while(x)
{
a[++k]=x%2;x/=2;
}
return dfs(k,1,1,1,0,0,0);
}
signed main()
{
cin>>t;
while(t--){
int n;scanf("%lld",&n);
printf("%lld\n",solve(n)*3);
}
}
2022 蓝桥杯第13届模拟赛第1期
1.10000(含) 到 90000(含) 中,有多少个数是 128 的倍数。
#include <iostream>
#include <cstdio>
using namespace std;
int sum;
int main() {
for (int i = 10000; i <= 90000; i ++ ) {
if (i % 128 == 0) sum ++ ;
}
printf("%d\n", sum);
return 0;
}
2.2021 是一个特殊的年份,它的千位和十位相同,个位比百位多一。请问从 1000(含) 到 9999(含) 有多少个这样的年份?
#include <iostream>
#include <cstdio>
using namespace std;
int sum;
int main() {
for (int i = 1000; i <= 9999; i ++ ) {
int a = i / 1000, b = i % 1000 / 100, c = i % 100 / 10, d = i % 10;
if (a == c && b + 1 == d) sum ++ ;
}
printf("%d\n", sum);
return 0;
}
3.如果1到n 的一个排列中,所有奇数都在原来的位置上,称为一个奇不动排列,1到21的所有排列中,有多少个奇不动排列 11 奇数 10偶数
#include <iostream>
#include <cstdio>
using namespace std;
int sum = 1;
int main() {
for (int i = 1; i <= 10; i ++ ) {
sum *= i;
}
printf("%d\n", sum);
return 0;
}
4.上一个楼梯,共 15 级台阶。
小蓝每步可以上 1 级台阶,也可以上 2 级、3 级或 4 级,再多就没办法一步走到了。
台阶上的数值依次为:1, 2, 1, 1, 1, 1, 5, 5, 4, -1, -1, -2, -3, -1, -91,2,1,1,1,1,5,5,4,−1,−1,−2,−3,−1,−9。
小蓝希望不超过 6 步走到台阶顶端,请问他得分的最大值是多少?
#include <iostream>
#include <cstdio>
using namespace std;
int INF = 1e9;
int a[16] = {0,1,2,1,1,1,1,5,5,4,-1,-1,-2,-3,-1,-9};
int f(int stair, int step) {
if (stair == 15) return a[15];
if (step == 0) return -INF;
int maxscore = -INF;
for (int i = 1; i <= 4; i ++ ) {
if (stair + i <= 15) {
int score = f(stair + i, step - 1) + a[stair];
if (score > maxscore) maxscore = score;
}
}
return maxscore;
}
int main() {
printf("%d\n", f(0, 6));
return 0;
}
5.在数列a[1],a[2],⋯,a[n] 中,如果对于下标 i, j, k 满足 0<i<j<k<n+1 且 a[i]<a[j]<a[k],则称 a[i], a[j], a[k]为一组递增三元组。
请问对于下面的长度为 20 的数列,有多少个递增三元组?
2,9,17,4,14,10,25,26,11,14,16,17,14,21,16,27,32,20,26,36
#include <iostream>
#include <cstdio>
using namespace std;
int sum;
int a[21] = {0,2,9,17,4,14,10,25,26,11,14,16,17,14,21,16,27,32,20,26,36};
int main() {
int n = 20;
for (int i = 1; i < n + 1; i ++ ) {
for (int j = i + 1; j < n + 1; j ++ ) {
for (int k = j + 1; k < n + 1; k ++ ) {
if (a[i] < a[j] && a[j] < a[k]) sum ++ ;
}
}
}
printf("%d\n", sum);
return 0;
}
6.小蓝开车在高速上行驶了 t 小时,速度固定为每小时 v 千米,请问小蓝在高速上行驶了多长路程
#include <iostream>
#include <cstdio>
using namespace std;
long long t, v;
int main() {
scanf("%lld %lld", &t, &v);
printf("%lld\n", t * v);
return 0;
}
7.现在对这个棋盘进行黑白染色,左上角染成黑色。从左上角开始,每个黑 色格的相邻格染成白色,白色格的相邻格染成黑色。
#include <iostream>
#include <cstdio>
using namespace std;
long long n, m, cnt;
int main() {
scanf("%lld %lld", &n, &m);
cnt = n * m;
if (cnt % 2 == 0) {
printf("%lld\n", cnt / 2);
} else {
printf("%lld\n", cnt / 2 + 1);
}
return 0;
}
8.在路边划分停车位
编号1~L整数块,一个车位要连续k小块,不能停车n小块编号1-n
#include <iostream>
#include <cstdio>
using namespace std;
int l, k, n, a[100010], ans;
int main() {
scanf("%d%d%d", &l, &k, &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
a[0] = 0;
a[n + 1] = l + 1;
for (int i = 1; i <= n + 1; i ++ ) {
ans += (a[i] - a[i - 1] - 1) / k;
}
printf("%d\n", ans);
return 0;
}
9.人字排列 1~n全排列,多少个
一个 1 到 n 的排列被称为人字排列,是指排列中的第 1 到第 (n+1)/2个元素单调递增,第 (n+1)/2到第 n 个元素单调递减。
#include <iostream>
#include <cstdio>
using namespace std;
const int MOD = 1e9 + 7;
int n, c[1001][1001];
int main() {
scanf("%d", &n);
c[1][0] = c[1][1] = 1;
for (int i = 2; i <= n; i ++ ) {
c[i][0] = 1;
for (int j = 1; j <= i; j ++ ) {
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
}
}
printf("%d\n", c[n - 1][(n - 1) / 2]);
return 0;
}
10.输入一个整数,请在整数前面补 0 补足 8 位后输出
#include <iostream>
#include <cstdio>
using namespace std;
int n;
int main() {
scanf("%d", &n);
printf("%08d\n", n);
return 0;
}
11.请帮小蓝检查一下,是否教学楼1的任意两个地方都可以连通到其它地方
#include <iostream>
#include <cstdio>
using namespace std;
int n, m, total, cnt;
string a[500];
bool visited[500][500];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
void dfs(int x, int y) {
cnt ++ ;
visited[x][y] = true;
for (int d = 0; d < 4; d ++ ) {
int nx = x + dx[d], ny = y + dy[d];
if (0 <= nx && nx < n && 0 <= ny && ny < m && a[nx][ny] == '1' && !visited[nx][ny]) {
dfs(nx, ny);
}
}
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i ++ ) {
cin >> a[i];
for (int j = 0; j < m; j ++ ) {
if (a[i][j] == '1') total ++ ;
}
}
for (int i = 0; i < n; i ++ ) {
for (int j = 0; j < m; j ++ ) {
if (a[i][j] == '1') {
dfs(i, j);
if (cnt == total) cout << "YES" << endl;
else cout << "NO" << endl;
return 0;
}
}
}
return 0;
}
2022 蓝桥杯第13届模拟赛第2期
1.小蓝的IP地址为 192.168.*.21
,其中 *
是一个数字,请问这个数字最大可能是多少?
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
printf("255");
return 0;
}
2.请问在 11(含) 到 20212021(含) 中,有多少个数与 20212021 存在大于 11 的公约数。
#include <iostream>
#include <cstdio>
using namespace std;
int sum;
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
int main() {
for (int i = 1; i <= 2021; i ++ ) {
if (gcd(i, 2021) > 1) sum ++ ;
}
printf("%d\n", sum);
return 0;
}
3.是一个非常特殊的数,它可以表示成两个非负整数的平方差;在 1 到 2021 中有多少个这样的数
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int sum;
int main() {
for (int i = 1; i <= 2021; i ++ ) {
bool flag = false;
for (int j = 0; j <= 2021; j ++ ) {
int x = j * j + i;
if ((int)sqrt(x) * (int)sqrt(x) == x) flag = true;
}
if (flag) sum ++ ;
}
printf("%d\n", sum);
return 0;
}
4.a 出现 10 次,b 出现 20 次,c 出现 3 次,d 出现 4 次,e 出现 18 次,f 出现 50 次
5 3 4
4 7 10
3 17 18
2 35 20
1 55 50
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
printf("%d", (3 + 4) * 5 + 10 * 4 + 18 * 3 + 20 * 2 + 50 * 1);
return 0;
}
5.下面的矩阵中包含 ABCDEF 六种字符,请问出现最多的字符出现了几次 78
/*
FFEEFEAAECFFBDBFBCDA
DACDEEDCCFFAFADEFBBA
FDCDDCDBFEFCEDDBFDBE
EFCAAEECEECDCDECADDC
DFAEACECFEADCBFECADF
DFBAAADCFAFFCEADFDDA
EAFAFFDEFECEDEEEDFBD
BFDDFFBCFACECEDCAFAF
EFAFCDBDCCBCCEADADAE
BAFBACACBFCBABFDAFBE
FCFDCFBCEDCEAFBCDBDD
BDEFCAAAACCFFCBBAAEE
CFEFCFDEEDCACDACECFF
BAAAFACDBFFAEFFCCCDB
FADDDBEBCBEEDDECFAFF
CDEAFBCBBCBAEDFDBEBB
BBABBFDECBCEFAABCBCF
FBDBACCFFABEAEBEACBB
DCBCCFADDCACFDEDECCC
BFAFCBFECAACAFBCFBAF
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
char ch[20][20];
int a[6], sum;
int main() {
for (int i = 0; i < 20; i ++ ) {
scanf("%s", ch[i]);
for (int j = 0; j < 20; j ++ ) {
a[ch[i][j] - 'A'] ++ ;
}
}
for (int i = 0; i < 6; i ++ ) {
sum = max(sum, a[i]);
}
printf("%d\n", sum);
return 0;
}
6.铅笔必须一整盒一整盒买,一整盒 12 支,价格 p 元。
小蓝至少要买 t* 支铅笔,请问他最少花多少钱?
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
int p, t;
scanf("%d %d", &p, &t);
printf("%d", (t + 11) / 12 * p);
return 0;
}
7.给定一个三角形的三条边的长度 a,b,c,请问这个三角形是不是一个直角三角形。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int a[3];
int main() {
for (int i = 0; i < 3; i ++ ) {
scanf("%d", &a[i]);
}
sort(a, a + 3);
if (a[0] * a[0] + a[1] * a[1] == a[2] * a[2]) {
printf("YES\n");
} else {
printf("NO\n");
}
return 0;
}
8.小秘密
n 个小朋友正在做一个游戏,每个人要分享一个自己的小秘密。
每个小朋友都有一个 1 到 n 的编号,编号不重复。
为了让这个游戏更有趣,老师给每个小朋友发了一张卡片,上面有一个 1 到 n 的数字,每个数字正 好出现一次。
每个小朋友都将自己的秘密写在纸上,然后根据老师发的卡片上的数字将秘密传递给对应编号的小 朋友。如果老师发给自己的数字正好是自己的编号,这个秘密就留在自己手里。
小朋友们拿到其他人的秘密后会记下这个秘密,老师会再指挥所有小朋友将手中的秘密继续传递,仍然根据老师发的卡片上的数字将秘密传递给对应编号的小朋友。
这样不断重复 n 次。
现在,每个小朋友都记下了很多个秘密。
老师现在想找一些小朋友,能说出所有秘密,请问老师最少要找几个小朋友?
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], n, sum;
bool f[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
for (int i = 1; i <= n; i ++ ) {
if (!f[i]) {
sum ++ ;
int k = i;
while (a[k] != i) {
k = a[k];
f[k] = true;
}
}
}
printf("%d\n", sum);
return 0;
}
9.半递增序列
一个 1 到 n 的排列被称为半递增序列,是指排列中的奇数位置上的值单调递增,偶数位置上的值也 单调递增。
#include <iostream>
#include <cstdio>
using namespace std;
const int MOD = 1e9 + 7;
int n, c[1001][1001];
int main() {
scanf("%d", &n);
c[1][0] = c[1][1] = 1;
for (int i = 2; i <= n; i ++ ) {
c[i][0] = 1;
for (int j = 1; j <= i; j ++ ) {
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
}
}
printf("%d\n", c[n][n / 2]);
return 0;
}
10.输入一个整数,请在整数前后补上等号,使得总的长度为 10,而且整数在正中间。
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
string s;
cin >> s;
int r = (10 - s.size()) / 2, l = 10 - r - s.size();
for (int i = 1; i <= l; i ++ ) printf("=");
cout << s;
for (int i = 1; i <= r; i ++ ) printf("=");
return 0;
}
11.人行道
小蓝住在 LQ 城,今天他要去小乔家玩。
LQ 城可以看成是一个 n 行 m 列的一个方格图。
小蓝家住在第 11 行第 11 列,小乔家住在第 n 行第 m 列。
小蓝可以在方格图内走,他不愿意走到方格图外。
城市中有的地方是风景优美的公园,有的地方是熙熙攘攘的街道。小蓝很喜欢公园,不喜欢街道。 他把方格图中的每一格都标注了一个属性,或者是喜欢的公园,标为 1,或者是不喜欢的街道标为2。小 蓝和小乔住的地方都标为了 1。
小蓝每次只能从一个方格走到同一行或同一列的相邻方格。他想找到一条路径,使得不连续走两次 标为 2 的街道,请问在此前提下他最少要经过几次街道?
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
int n, m;
string a[300];
bool visited[300][300];
int dis[300][300];
deque<pair<int, int>> q;
int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
void bfs(int sx, int sy) {
q.push_back({sx, sy});
dis[sx][sy] = 0;
visited[sx][sy] = true;
while (!q.empty()) {
pair<int, int> p = q.front();
q.pop_front();
int x = p.first;
int y = p.second;
for (int d = 0; d < 4; d ++ ) {
int nx = x + dx[d];
int ny = y + dy[d];
if (0 <= nx && nx < n && 0 <= ny && ny < m && !visited[nx][ny]) {
if (a[x][y] == '1' && a[nx][ny] == '2') {
q.push_back({nx, ny});
visited[nx][ny] = true;
dis[nx][ny] = dis[x][y] + 1;
} else if (a[nx][ny] == '1') {
q.push_front({nx, ny});
visited[nx][ny] = true;
dis[nx][ny] = dis[x][y];
}
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i ++ ) cin >> a[i];
bfs(0, 0);
if (!visited[n - 1][m - 1]) cout << -1 << endl;
else cout << dis[n - 1][m - 1] << endl;
return 0;
}
2022 蓝桥杯第13届模拟赛第3期
1.十六进制 539077581
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
string s = "2021ABCD";
// 01234567
int res = s[0] - '0';
for (int i = 0; i <= 3; i ++ ) {
res = res * 16 + s[i] - '0';
}
for (int i = 4; i <= 7; i ++ ) {
res = res * 16 + s[i] - 'A' + 10;
}
printf("%d\n", res);
return 0;
}
2.倍数 最小公倍数
#include <cstdio>
#include <iostream>
using namespace std;
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b) {
return a / gcd(a, b) * b;
}
int sum;
int main() {
for (int i = 1; i <= 2021; i ++ ) {
if (lcm(i, 2021) == 4042) sum ++ ;
}
printf("%d\n", sum);
return 0;
}
3.两个平方数之和
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
int sum;
// x = i * i + j * j
int a[100010];
int main() {
for (int i = 0; i <= 45; i ++ ) {
for (int j = 0; j <= 45; j ++ ) {
a[i * i + j * j] ++ ;
}
}
for (int i = 1; i <= 2021; i ++ ) {
if (a[i] > 0) sum ++ ;
}
printf("%d\n", sum);
return 0;
}
4.最小生成树
5.子矩阵和
/* 154
69859241839387868941
17615876963131759284
37347348326627483485
53671256556167864743
16121686927432329479
13547413349962773447
27979945929848824687
53776983346838791379
56493421365365717745
21924379293872611382
93919353216243561277
54296144763969257788
96233972513794732933
81443494533129939975
61171882988877593499
61216868895721348522
55485345959294726896
32124963318242554922
13593647191934272696
56436895944919899246
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 25;
int a[N][N], s[N][N];
char ch[20][20];
int ans;
int main() {
for (int i = 0; i < 20; i ++ ) {
scanf("%s", ch[i]);
for (int j = 0; j < 20; j ++ ) {
a[i + 1][j + 1] = ch[i][j] - '0';
}
}
for (int i = 1; i <= 20; i ++ ) {
for (int j = 1; j <= 20; j ++ ) {
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
}
}
for (int i = 1; i <= 16; i ++ ) {
for (int j = 1; j <= 16; j ++ ) {
int sum = s[i + 4][j + 4] - s[i - 1][j + 4] - s[i + 4][j - 1] + s[i - 1][j - 1];
ans = max(sum, ans);
}
}
printf("%d\n", ans);
return 0;
}
6.显示网页
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
int t, a, p;
scanf("%d %d %d", &t, &a, &p);
/*
int m = t / a, ans1, ans2;
if (t % a != 0) m ++ ;
if (p == m) ans1 = (m - 1) * a + 1, ans2 = t;
else ans1 = (p - 1) * a + 1, ans2 = p * a;
printf("%d %d\n", ans1, ans2);
*/
printf("%d %d\n", a * (p - 1) + 1, min(t, a * p));
return 0;
}
7.数位递增
#include <iostream>
#include <cstdio>
using namespace std;
string s;
int main() {
getline(cin, s);
for (int i = 0; i + 1 < s.size(); i ++ ) {
if (s[i] - '0' >= s[i + 1] - '0') {
printf("NO\n");
return 0;
}
}
printf("YES\n");
return 0;
}
8.停车场
#include <iostream>
#include <cstdio>
using namespace std;
// 同一天 h1 < h2
int h1, h2, m1, m2, s1, s2;
int main() {
scanf("%d:%d:%d", &h1, &m1, &s1);
scanf("%d:%d:%d", &h2, &m2, &s2);
int len = (h2 - h1) * 3600 + (m2 - m1) * 60 + s2 - s1;
printf("%02d:%02d:%02d", len / 3600, len % 3600 / 60, len % 60);
return 0;
}
9.运动员
/*
状压排序
由于运动员个数不超过 100 名,可以将成绩乘以 107 再加上运动员的编号,进行状态压缩,当然也可以用 pair
用矩阵竖着放,每行存某项运动每名运动员的成绩与编号,然后对每行降序排序
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 105;
int a[MAXN][MAXN];
int ans[MAXN];
bool cmp(int x, int y) {
return x > y;
}
int main() {
int n, m, k;
cin >> n >> m >> k;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> a[j][i];
a[j][i] = a[j][i] * 107 + i;
}
}
for (int i = 0; i < m; i++) {
sort(a[i], a[i] + n, cmp);
for (int j = 0; j < k && j < n; j++) {
int idx = a[i][j] % 107;
ans[idx] += k - j;
}
}
for (int i = 0; i < n; i++) {
cout << ans[i];
if (i != n - 1) cout << " ";
}
cout << endl;
return 0;
}
10.最长上升子序列,并且每集合不少于下标的数 java实现
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int k = in.nextInt();
int[] a = new int[n + 1];
for (int i = 1; i <= n; i++)
a[i] = in.nextInt();
String ss = in.next();
char[] s = ss.toCharArray();
int[][] dp = new int[n + 1][k + 1];
int ans = 0;
dp[0][0] = 0;
for (int i = 1; i <= k; i++)
dp[0][i] = Integer.MIN_VALUE;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= k; j++) {
int y = j;
if (j > 0 && s[i - 1] == '1')
y--;
//这里先让它为负无穷的原因是怕它不合法,就是不满足列号要求
//如果它合法,自然能从前面找个非负数,然后加1取代现在的值
dp[i][j] = Integer.MIN_VALUE;
for (int p = 0; p < i; p++)
if (a[p] < a[i] && dp[p][y] + 1 > dp[i][j])
dp[i][j] = dp[p][y] + 1;
}
if (dp[i][k] > ans)
ans = dp[i][k];
}
System.out.println(ans);
}
}
2022 蓝桥杯第13届省赛模拟赛
1.求A个数 318
/*
AAAAAAABABBAABABABAAAAAAA
ABBBBBABBAABBBBBABABBBBBA
ABAAABABBBABAABBBBABAAABA
ABAAABABBBBBAABAABABAAABA
ABAAABABBABABBABABABAAABA
ABBBBBABBBABAABBBBABBBBBA
AAAAAAABABABABABABAAAAAAA
BBBBBBBBABAABABBBBBBBBBBB
AABAABABBAAABBAAABABBBBBA
ABBABABBBABBAAAABBBBAAAAB
BBBBAAABABAABABAABBBAABBA
BBAABABABAAAABBBAABBAAAAA
ABABBBABAABAABABABABBBBBA
AAAABBBBBABBBBAAABBBABBAB
AABAABAAABAAABAABABABAAAA
ABBBBBBBBABABBBBABAABBABA
ABBBAAABAAABBBAAAAAAABAAB
BBBBBBBBABBAAABAABBBABBAB
AAAAAAABBAAABBBBABABAABBA
ABBBBBABBAABABAAABBBABBAA
ABAAABABABBBAAAAAAAAAABAA
ABAAABABABABBBABBAABBABAA
ABAAABABBABBABABAABAABAAA
ABBBBBABABBBBBABBAAAABAAA
AAAAAAABAABBBAABABABBABBA
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
char g[25][25];
int sum;
int main() {
for (int i = 0; i < 25; i ++ ) {
scanf("%s", g[i]);
for (int j = 0; j < 25; j ++ ) {
if (g[i][j] == 'A') {
sum ++ ;
}
}
}
printf("%d\n", sum);
return 0;
}
2.最2数个数 564
#include <iostream>
#include <cstdio>
using namespace std;
int sum;
int main() {
for (int i = 1; i <= 2021; i ++ ) {
int t = i;
bool flag = false;
while (t > 0) {
if (t % 10 == 2) {
flag = true;
break;
}
t /= 10;
}
if (flag) sum ++ ;
}
printf("%d\n", sum);
return 0;
}
3.变为1最小操作次数偶数除2奇数加减 14
#include <iostream>
#include <cstdio>
using namespace std;
int n;
int f(int n) {
if (n == 1)
return 0;
if (n % 2 == 0)
return 1 + f(n / 2);
if (n == 3)
return 2;
if (n & 2)
return 1 + f(n + 1);
else {
return 1 + f(n - 1);
}
}
int main() {
scanf("%d", &n);
printf("%d\n", f(n));
return 0;
}
4.螺旋矩阵 819 n = 30 i = 20 j = 20
#include <iostream>
#include <cstdio>
using namespace std;
int res[100][100];
int n, i, j;
int work(int n, int i, int j) {
if (i == 1)
return j;
if (j == n)
return n + i - 1;
if (i == n)
return 3 * n - 2 - j + 1;
if (j == 1)
return 4 * n - 4 - i + 2;
return work(n - 2, i - 1, j - 1) + 4 * (n - 1);
}
int main() {
scanf("%d %d %d", &n, &i, &j);
printf("%d", work(n, i, j));;
return 0;
}
5.二叉树深度 10
#include <iostream>
#include <cstdio>
using namespace std;
int f(int n) {
return 1 << (n - 1);
}
int sum;
int main() {
for (int i = 1; sum <= 2021; i ++ ) {
sum += f(i);
printf("%d %d %d\n", i, f(i), sum);
}
return 0;
}
6.最少搬几次
#include <iostream>
#include <cstdio>
using namespace std;
int a, t;
int ans;
int main() {
scanf("%d %d", &a, &t);
if (a >= t) ans = 1;
else {
if (t % a) ans = t / a + 1;
else ans = t / a;
}
printf("%d\n", ans);
return 0;
}
7.字符串去逗号
#include <iostream>
#include <cstdio>
using namespace std;
string t, b;
int main() {
getline(cin, t);
for (int i = 0; i < t.size(); i ++ ) {
if (t[i] != ',') {
b += t[i];
}
}
cout << b << endl;
return 0;
}
8.模拟插板求下标
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 110;
char a[N][N], b[N][N];
int n, m, r, c;
int main() {
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%s", &a[i]);
scanf("%d %d", &r, &c);
for (int i = 0; i < r; i ++ ) scanf("%s", &b[i]);
for (int i = 0; i <= n - r; i ++ ) {
for (int j = 0; j <= m - c; j ++ ) {
bool flag = true;
for (int k = i; k <= i + r - 1; k ++ ) {
for (int l = j; l <= j + c - 1; l ++ ) {
if (a[k][l] == '0' && b[k - i][l - j] == '1') {
flag = false;
break;
}
}
}
if (flag) {
printf("%d %d\n", i + 1, j + 1);
return 0;
}
}
}
printf("NO\n");
return 0;
}
9.数论
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
set<long long> get_divisors(long long x)
{
set<long long> res;
res.clear();
for (long long i = 1; i <= x / i; i ++ )
if (x % i == 0)
{
res.insert(i);
if (i != x / i) res.insert(x / i);
}
return res;
}
int main()
{
long long x, y ,z;
scanf("%lld %lld %lld", &x, &y, &z);
set<long long> s1 = get_divisors(x), s2 = get_divisors(y), s3 = get_divisors(z), s;
for (auto x : s1) {
if (s2.count(x)) s.insert(x);
if (s3.count(x)) s.insert(x);
}
for (auto x : s2) {
if (s3.count(x)) s.insert(x);
}
printf("%lld\n", s.size());
return 0;
}
10.模拟递归汉诺塔
#include<cstdio>
int n, last[55], first[55], ans, m, x;
int a, b, c;
void dfs(int x, int y)
{
if (first[x] == y) return;
for(int i = x - 1 ;i >= 1; i -- )
dfs(i, 6 - (first[x] + y));
first[x] = y;
ans ++ ;
}
int main()
{
scanf("%d %d %d",&a, &b, &c);
n = a + b + c;
while (a -- ) {
int x; scanf("%d", &x); first[x] = 1;
}
while (b -- ) {
int x; scanf("%d", &x); first[x] = 2;
}
while (c -- ) {
int x; scanf("%d", &x); first[x] = 3;
}
for (int i = n; i >= 1; i -- ) last[i] = 3;
for (int i = n; i >= 1; i -- ) dfs(i, last[i]);
printf("%d", ans);
return 0;
}