2022蓝桥杯初赛C/C++B组题解

A:九进制转十进制
#include<iostreamod>  //1 
#include<cmath>
using namespace std;
int main()
{
int n=2022;
int count=0,num=0;
while(n)
{
num+=(n%10)*pow(9,count);
n/=10;
count++;
}
printf("%d\n",num);
return 0;
}
B:顺子日期
#include<iostream>      //2
using namespace std;
int main()
{
cout<<14<<endl;
return 0;
}
C:刷题统计
#include<iostream>     /3
using namespace std;
//sum为一周做题数,x为做了多少周,m为周几做 
int main()
{
long long int a,b,n,x,m,num=0;
cin>>a>>b>>n;
long long int sum=5*a+2*b;
x=n/sum;
n-=sum*x;
m=n/a;
if(m>=5)
{
n-=5*a;
if(n>b)
num=7;
else
num=6;
} 
else
{
if(n%a==0)
num=m;
else
num=m+1;
}
num+=7*x;
cout<<num<<endl;
return 0;
} 
D:修建灌木
#include<iostream>    //4
#include<algorithm>
using namespace std;
const int N=1e4+10;
int a[N];
int main() 
{
int n;
cin>>n;
for(int i=1;i<=n-i+1;i++)
{
a[i]=2*(n-i);
a[n-i+1]=a[i];
}
for(int i=1;i<=n;i++)
{
cout<<a[i]<<endl;
}
return 0;
}
E:X进制减法
#include<iostream>      //5
#include<algorithm>
#include<cmath> 
#include<cstring>
using namespace std;
const int N=1e6+10;
long long int a[N],b[N]={0},c[N];
int main()
{
long long int n,ma,mb;
cin>>n;
cin>>ma;
for(int i=ma;i>=1;i--)
{
cin>>a[i];
}
cin>>mb;
for(int i=mb;i>=1;i--)
{
cin>>b[i];
    }
    for(int i=ma;i>=1;i--)
{
c[i]=max(a[i],b[i])+1;
if(c[i]<2)
{
c[i]=2;
}
}
long long int x=1,cha=0;
    for(int i=1;i<=ma;i++)
    {
    cha+=((a[i]-b[i])*x)%1000000007;
    x*=c[i];
    x=x%1000000007;
    }
    cout<<cha%1000000007<<endl;
    return 0;
}
F:统计子矩阵
#include<iostream>
#include<algorithm>
using namespace std;
const int N=666;
long long int a[N][N],b[N][N];
int main()
{
long long int n,m,k,num=0;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
b[i][j]=b[i-1][j]+a[i][j];
}
}
long long int l=1,sum=0;
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
l=1;
sum=0;
for(int r=1;r<=m;r++)
{
long long int r1=b[j][r]-b[i-1][r];
if(sum+r1<=k)
{
sum+=r1;
num+=r-l+1;
} 
else
{
long long int l1=b[j][l]-b[i-1][l];
while(l!=r&&sum+r1>k)
{
sum-=l1;
l++;
l1=b[j][l]-b[i-1][l];
}
if(sum+r1<=k)
{
sum+=r1;
num+=r-l+1;
}
else
l++;
}
}
}
}
cout<<num<<endl;
return 0;
}
G:积木画

本题是一个dp问题,由于用二维dp比较麻烦,可以使用一维dp,将I型积木看成一个格子,L型积木为1.5个格子,所以L型积木必须要2个一组,由于I型积木有竖着摆和横着摆2种方式,所以要乘2;

所以递推公式为:x[i]=2*x[i-1]+x[i-3];

#include<iostream>
#include<algorithm>
using namespace std;
const int mod=1000000007;
const int N=1e7+10;
long long int x[N];
int main()
{
long long int n;
cin>>n;
x[1]=1;
x[2]=2;
x[3]=5;
for(int i=4;i<=n;i++)
{
x[i]=(2*x[i-1]%mod+x[i-3]%mod)%mod;
}
cout<<x[n]%mod<<endl;
return 0;
} 
H:扫雷
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N = 5e4 + 10, M = 1e6 + 7, X = 1e9 + 1;
int n, m;
struct node {int x, y, r;}b[N];
typedef long long ll;
ll Hash[M]; bool vis[N];
int id[M], res; 
ll get_hs(int x, int y) { return (ll)x * X + y; }
int find(int x, int y) {
ll hs = get_hs(x, y);
int key = (hs % M + M) % M; 
while (Hash[key] != -1 && Hash[key] != hs) {
key++;
if (key == M) key = 0; 
} return key;
}
bool check(int x1, int y1, int r, int x, int y) {
int d = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y);
return d <= r * r;
}
void bfs(int pos) {
queue<int> q;
q.push(pos);
vis[pos] = 1;
while (q.size()) {
int t = q.front();
q.pop();
int x = b[t].x, y = b[t].y, r = b[t].r;
for (int xx = x - r; xx <= x + r; xx++) { 
for (int yy = y - r; yy <= y + r; yy++) {
int key = find(xx, yy);
if (id[key] && !vis[id[key]] && check(x, y, r, xx, yy)) {
int pos = id[key];
vis[pos] = 1;
q.push(pos);
}
}
}
}
}
int main() {
cin >> n >> m;
memset(Hash, -1, sizeof(Hash));
int x, y, r;
for (int i = 1; i <= n; i++) { 
cin >> x >> y >> r;
b[i] = { x, y, r };
int key = find(x, y);
if (Hash[key] == -1) Hash[key] = get_hs(x, y); 
if (!id[key] || b[id[key]].r < r) id[key] = i;
}
for (int i = 1; i <= m; i++) { 
cin >> x >> y >> r;
for (int xx = x - r; xx <= x + r; xx++) 
for (int yy = y - r; yy <= y + r; yy++) {
int key = find(xx, yy);
if (id[key] && !vis[id[key]] && check(x, y, r, xx, yy)) bfs(id[key]);
}
}
for (int i = 1; i <= n; i++) {
int key = find(b[i].x, b[i].y); 
int pos = id[key];
if (pos && vis[pos]) res++; 
}
cout << res;
return 0;
}
I:李白打酒加强版

状态设计:dp[i][j][k]的值表示遇到i家店,j朵花,酒壶中还剩k斗酒的可能情况数;

状态转移方程:dp[i][j][k]=dp[i-1][j][k/2](i>1&&k%2==0) + dp[i][j-1][k+1](j>1);

边界设计:除了dp[0][0][2]=1,其他元素全为0;

他一共遇到店n次,遇到花m次。已知最后一次遇到的是花, 他正好把酒喝光了;所以

最后一次肯定遇到的是花,那么最后的结果便是dp[N][M-1][1];

#include<iostream>
#include<cstring>
using namespace std;
const int mod=1000000007,N=110;
long long dp[N * 2][N][N];    /* 店,花,酒 */
void slove()
{
    int n, m;
    cin>>n>>m;
    memset(dp, 0, sizeof dp);
    dp[0][0][2] = 1;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
            for(int k=0;k<=m;k++) 
{
                if(i&&k%2==0)
                    dp[i][j][k]+=dp[i-1][j][k/2]; /* 遇到店 */
                if (j)
                    dp[i][j][k]+=dp[i][j-1][k+1]; /* 遇到花 */
                dp[i][j][k]%=mod;
            }
    cout<<dp[n][m-1][1]<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
{
slove();
}
return 0;
}
J:砍竹子

贪心,先将高的竹子砍了,可能这些竹子之后会和矮的竹子一起砍了。然后用a[i][j]记录第i棵树砍了j次后的高度,开始的砍树次数就是所有的树都一次一次地砍为 1 所需要的次数和,然后遍历如果发现有相邻的两棵树高度相同我们的砍树次数就可以减少1 。

#include<iostream>
#include<algorithm>
#include<cmath>
typedef long long int ll;
using namespace std;
const int N=2e5+10;
ll a[N][8],b[8];
int main()
{
ll num=0,n,x,t;
cin>>n;
for(int i=1;i<=n;i++)
{
t=0;
cin>>x;
while(x!=1)
{
b[++t]=x;
x=sqrt(x/2+1);
}
num+=t;
for(int j=1;t>0;j++,t--)
{
a[i][j]=b[t];
}
}
for(int i=1;i<=7;i++)
{
for(int j=2;j<=n;j++)
{
if(a[j][i]&&a[j][i]==a[j-1][i])
num--;
}
}
cout<<num<<endl;
return 0;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值