蓝桥杯2022省赛b组题解

文章包含一系列编程问题的解决方案,如九进制到十进制的转换,寻找特定日期的顺子,计算特定条件下的刷题次数,解决二维数组子矩阵的统计问题,以及包括扫雷在内的各种逻辑推理和数学运算的编程挑战。这些题目涉及到了进制系统、循环、数组操作、哈希表和深度优先搜索等编程概念和技术。
摘要由CSDN通过智能技术生成

九进制转十进制

利用进制转换的公式即可

#include<iostream>
#include<cmath>
using namespace std;
int year=2022;
int ans=0,a=0;
int main(){
  while(year){
    res+=(int)pow(9,a)*(year%10);
    year/=10;
    a++;}
   cout<<ans;
   return 0;
}

顺子日期

顺子每两个数之间差一

#include<iostream>
using namespace std;
int ans = 0;
int month[12] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int day[12] = { 31,29,31,30,31,30,31,31,30,31,30,31 };//打表
int main() {
    for (int i = 0; i < 12; i++) {
        for (int k = 1; k <= day[i]; k++) {
            int a = month[i] % 10 - month[i] / 10;//差值
            int b = k / 10 - month[i] % 10;//差值2
            int c = k % 10 - k / 10;//差值三
            if(a == 1 && b == 1)ans++;
            if (c == 1&& b == 1)ans++;
            if (a == 1 && b == 1 && c == 1)ans--;
        }
    }
    cout << ans;
    return 0;
}

刷题统计

先算整周的倍数,余下的天数直接枚举

#include<iostream>
using namespace std;
long long n, a, b,ans=0;
int main() {
    cin >> a >> b >> n;
    long long week = 5 * a + 2 * b;
    if (n % week > 0 && n % week <= a)ans += 1;
    if (n % week > a && n % week <= a*2)ans += 2;
    if (n % week > a*2 && n % week <= a*3)ans += 3;
    if (n % week > a*3 && n % week <= a*4)ans += 4;
    if (n % week > a*4 && n % week <= a*5)ans += 5;
    if (n % week > a*5 && n % week <= a*5+b)ans += 6;
    if (n % week > a * 5+b && n % week <= a * 5 + 2*b)ans += 7;//数据不大直接枚举
    ans += n / week * 7;
    cout << ans;
    return 0;
}

修减灌木

找规律罢了

#include<iostream>
using namespace std;
int main(){
  int n;
  cin>>n;
  for(int i=1;i<=n;i++)
 {
    cout<<max(2*(i-1),2*(n-i))<<endl;}//规律
  return 0;
}

x进制减法

找规律,模拟


#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=1e5+5,M=1e9+7;
int a[N],b[N];
int main(){
    int n,na,nb;
    cin>>n;
    cin>>na;
    for(int i=na;i>0;i--){
        scanf("%d",&a[i]);
    }
    cin>>nb;
    for(int i=nb;i>0;i--){
        scanf("%d",&b[i]);
    }
    long long sum=0;
    for(int i=na;i>0;i--){
        sum=sum*max(2,max(a[i],b[i])+1)%M;
        sum=((sum+a[i]-b[i])%M+M)%M;
    }
    cout<<sum;
    return 0;
}

统计子矩阵

二维数组的前缀和(直接模拟会tle)

#include<iostream>
#include<cstdio>
using namespace std;
int a[501][501],s[501][501];
long long ans;
int main(){
    int n,m,k;
    cin>>n>>m>>k;
 
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            s[i][j]=s[i-1][j]+a[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=i;j<=n;j++){
            int sum=0;
            for(int l=1,r=1;r<=m;r++){
                sum+=s[j][r]-s[i-1][r];
                while(sum>k) sum-=(s[j][l]-s[i-1][l]),l++;
                ans+=r-l+1;
            }
        }
    }
    printf("%lld",ans);
    return 0;
}

堆积木

列举出末尾的排列情况,求和即可(l方块可以正反放置,所以要乘2)

#include <bits/stdc++.h>
const int M=1e9+7;
int F[1000010];                
int preF[1000010];            
int n;
int main(){
    std::cin >> n;
    F[0] = 1;
    preF[0]=1;
    for(int i=1; i<=n; i++){
        F[i]=(i-1<0?0:preF[i-1])+(i-3<0?0:preF[i-3]);     
        F[i] %= M;                                
        preF[i] = preF[i-1]+F[i];                        
        preF[i] %= M;
    }
    std::cout << F[n] << std::endl;        
    return 0;
}

扫雷

哈希,dfs

#include <bits/stdc++.h>
using namespace std;
const int N = 50010, M = 999997;
struct circle {
    int x, y, r;
}cir[N];
int id[M];
bool sc[M];
#define ll long long
ll h[M];
ll get_key(int x, int y) {
    return x * 1000000001ll + y;
}
int find(int x, int y) {
    ll key = get_key(x, y);
    int t = (key%M + M) % M;
    while (h[t] != -1 && h[t] != key) {
        if (++t == M)t = 0;
    }
    return t;
}
int sqr(int x) {
    return x*x;
}
void dfs(int x, int y, int r) {
    sc[find(x, y)] = true;
    for (int i = x - r; i <= x + r; i++) {
        for (int j = y - r; j <= y + r; j++) {
            if (sqr(i-x) + sqr(j-y) <= sqr(r)) {
                int t = find(i, j);
                if (id[t] && !sc[t]) {
                    dfs(i, j, cir[id[t]].r);
                }
            }
        }
    }
}
 
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof(h));
    for (int i = 1; i <= n; i++) {
        int x, y, r;
        scanf("%d%d%d", &x, &y, &r);
        cir[i] = { x,y,r };
        int t = find(x, y);
        if (h[t] == -1)h[t] = get_key(x, y);
        if (!id[t] || cir[id[t]].r < r)id[t] = i;
 
 
    }
    while (m--) {
        int x, y, r;
        scanf("%d%d%d", &x, &y, &r);
        for (int i = x - r; i <= x + r; i++) {
            for (int j = y - r; j <= y + r; j++) {
                if (sqr(i-x) + sqr(j-y) <= sqr(r)) {
                    int t = find(i, j);
                    if (id[t] && !sc[t]) {
                        dfs(i, j, cir[id[t]].r);
                    }
 
                }
            }
        }
    }
    int res = 0;
    for (int i = 1; i <= n; i++) {
        if (sc[find(cir[i].x, cir[i].y)])res++;
    }
    printf("%d\n", res);
    return 0;
}

李白打酒加强版

dp,找规律,最后一次必遇到花

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=220,mod=1e9+7;
ll n,m,ans,len;
ll dp[N][N][N]; //前i次 有j次遇到店 剩下酒为k斗
int main()
{
    int t;
    cin>>t;
    while(t--){
 
    cin>>n>>m;      //N店  M花
    len=n+m;
    memset(&dp[0][0][0],0,sizeof(dp));
    dp[0][0][2]=1; //初始有2斗酒
    for(int i=1;i<=len;i++)
    for(int j=0;j<=n;j++)
    for(int k=0;k<=100;k++)
    {
        dp[i][j][k]+=dp[i-1][j][k+1]; //遇到花
        if(j&&k%2==0) dp[i][j][k]+=dp[i-1][j-1][k/2]; //遇到店
        dp[i][j][k]%=mod;
    }
    dp[len][n][0]=dp[len-1][n][1];  //最后遇到的一个一定是花
    cout<<dp[len][n][0]<<endl;
    }
    return 0;
}

砍竹子

#include<bits/stdc++.h>
using namespace std;
typedef pair<long long,int>PII;
priority_queue<PII>q;
int main()
{
    int n;
    cin>>n;
    long long ans=0;
    for(int i=1;i<=n;i++)
    {
        long long t;
        scanf("%lld",&t);
        if(t!=1)
        q.push({t,i});
    }
    while(!q.empty())
    {
        long long t=q.top().first;//记录当前竹子的高度 
        int r=q.top().second;//记录当前竹子的编号 
        q.pop();
        long long l=sqrt(t/2+1);
        if(l!=1)
            q.push({l,r});
        while(!q.empty()&&q.top().first==t&&q.top().second==r-1)
        {
            r--;
            q.pop();//将队首竹子pop 
            if(l!=1)
                q.push({l,r});//将砍完后的竹子放入优先队列 
        }
        ans++;//当发现竹子高度不一致或者编号不连续时记录一次砍的次数 
    }
    printf("%lld",ans);
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值