第十三届蓝桥杯省赛C/C++B组

博客 分享
0 295
张三
张三 2022-04-09 20:57:46
悬赏:0 积分 收藏

第十三届蓝桥杯省赛C/C++ B组

@

目录
  • A顺子日期
  • B顺子日期
  • C刷题统计
  • D 修剪灌木
  • E X进制减法
  • F统计子矩阵
  • G 积木画
  • H扫雷
  • I李白打酒加强版
  • J砍竹子

A顺子日期

答案是1478

B顺子日期

答案14(如果012算的话)

C刷题统计

数据范围1e18,所以不能直接暴力,先取余,再暴力剩下的

#include<bits/stdc++.h>using namespace std;#define rep(i,m,n) for(int i=m;i<=n;i++)#define per(i,m,n) for(int i=m;i>=n;i--)#define pair<int,int> PII#define int long longsigned main(){    int a,b,n;    cin>>a>>b>>n;    int ans=0,cnt=0;    int x=5*a+2*b;//一周刷题数    ans=n/x*7;    n=n%x;    while(1)    {        if(cnt>=n)            break;        ans++;        if(ans%7==0||ans%7==6)            cnt+=b;        else            cnt+=a;    }    cout<<ans;    return 0;}

D 修剪灌木

先读题
然后结论就是直接取左右两边最大的二倍

#include<bits/stdc++.h>using namespace std;#define pair<int,int> PII#define int long longconst int N=1e4+10;int a[N];signed main(){    int n;    cin>>n;    for(int i=1;i<=n;i++)    {        int l,r;        l=(i-1)*2;        r=(n-i)*2;        cout<<max(l,r)<<endl;    }    return 0;}

E X进制减法

这个题读了半天才懂,注意他说的进制是指逢几进一,
答案就是每一位取能取的最小进制
在这里插入图片描述
这里面的321=((3*10+2)*2)+1=65
也可以这样算 1+2*2+3*10*2=65

#include<bits/stdc++.h>using namespace std;#define pair<int,int> PII#define int long longconst int mod=1e9+7;const int N=1e4+10;int a[N],b[N],c[N],p[N];signed main(){    int k,ma,mb;    cin>>k>>ma;    for(int i=ma;i>=1;i--)        cin>>a[i];    cin>>mb;    for(int i=mb;i>=1;i--)        cin>>b[i];    int n=max(ma,mb);    for(int i=1;i<=n;i++)        c[i]=a[i]-b[i];    for(int i=n;i>=1;i--)    {        int pp=2;        pp=max(pp,max(a[i],b[i])+1);//最低p进制        p[i+1]=pp;    }    int ans=0;    for(int i=n;i>=2;i--)    {        c[i-1]+=c[i]*p[i];    }    cout<<c[1]<<endl;    return 0;}

F统计子矩阵

直接暴力的话(n^6) 铁炸!
使用前缀和+暴力的话(n^4) 也会炸
最后一维用二分优化(n^3*log n) 可能会炸,但我想不到更好的了

#include<bits/stdc++.h>using namespace std;#define pair<int,int> PII#define int long longconst int N=5e2+10;int a[N][N],sum[N][N];int n,m,K;int S(int x2,int y2,int x1,int y1){    return sum[x1][y1]-sum[x1][y2-1]-sum[x2-1][y1]+sum[x2-1][y2-1];}signed main(){    cin>>n>>m>>K;    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            cin>>a[i][j];    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];    int ans=0;    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)        {            if(a[i][j]>K)continue;            for(int k=i;k<=n;k++)            {                int l=j,r=m;                while(l<r)                {                    int mid=l+r+1>>1;                    if(S(i,j,k,mid)<=K)l=mid;                    else r=mid-1;                }                if(S(i,j,k,l)>K)continue;                //printf("%lld %lld %lld %lld\n",i,j,k,l);                ans+=(l-j+1);            }        }    }    cout<<ans<<endl;    return 0;}

G 积木画

状态压缩DP
f[i][j]表示已经摆完前i列,且突出来的状态为j
假如j=1:就是凸出来了上面那一块

#include<bits/stdc++.h>using namespace std;#define pair<int,int> PII#define int long longconst int mod=1e9+7;const int M=1<<2;const int N=1e7+10;int f[N][M];signed main(){    int n;    cin>>n;    f[0][0]=1;    for(int i=1;i<=n+1;i++)    {        f[i][0]=(f[i][0]+f[i-1][0]+f[i-1][3])%mod;//不突出        f[i][1]=(f[i][1]+f[i-1][2]+f[i-1][0])%mod;//上面突出        f[i][2]=(f[i][2]+f[i-1][1]+f[i-1][0])%mod;//下面突出        f[i][3]=(f[i][3]+f[i-1][0]+f[i-1][1]+f[i-1][2])%mod;//突出两个    }    cout<<f[n][0]<<endl;    return 0;}

第一维可以用滚动数组优化

#include<bits/stdc++.h>using namespace std;#define pair<int,int> PII#define int long longconst int mod=1e9+7;const int M=1<<2;int f[3][M];signed main(){    int n;    cin>>n;    f[0][0]=1;    for(int i=1;i<=n+1;i++)    {        f[i&1][0]=(f[i-1&1][0]+f[i-1&1][3])%mod;//不突出        f[i&1][1]=(f[i-1&1][2]+f[i-1&1][0])%mod;//上面突出        f[i&1][2]=(f[i-1&1][1]+f[i-1&1][0])%mod;//下面突出        f[i&1][3]=(f[i-1&1][0]+f[i-1&1][1]+f[i-1&1][2])%mod;//突出两个    }    cout<<f[n&1][0]<<endl;    return 0;}

H扫雷

直接两重循环建边+dfs搜索的,会炸(因为建边是两重循环,过不叫第二个5e4的样例)
注意不能并查集,因为a引爆b,但b不一定能引爆a
正解应该是看那个r(r<=10),不会....

#include<bits/stdc++.h>using namespace std;#define pair<int,int> PII#define int long longconst int N=1e3+10;vector<int> q[N];int x[N],y[N],r[N];int n,m;bool vis[N];bool v[N];int cnt;bool check(int x1,int y1,int r1,int x2,int y2){    return (x2-x1)*(x2-x1)+(y2-x1)*(y2-y1)<=r1*r1;//1会引炸2}void dfs(int x){    cnt++;    for(int i=0;i<q[x].size();i++)    {        int j=q[x][i];        if(vis[j]||v[N])continue;        v[j]=1;        dfs(j);    }}signed main(){    cin>>n>>m;    for(int i=1;i<=n;i++)    {        cin>>x[i]>>y[i]>>r[i];    }    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            if(i==j)continue;            if(check(x[i],y[i],r[i],x[j],y[j]))            {                q[i].push_back(j);            }        }    }    while(m--)    {        int xx,yy,rr;        cin>>xx>>yy>>rr;        for(int i=1;i<=n;i++)        {            if(check(xx,yy,rr,x[i],y[i]))            {                vis[i]=1;            }        }    }    for(int i=1;i<=n;i++)    {        if(vis[i])            dfs(i);    }    cout<<cnt<<endl;    return 0;}

I李白打酒加强版

dp,考虑遇到店或者花
f[i][j][k]表示已经走了i次,有j次经过了酒馆,还剩k斗酒
记录酒的时候只需要斗里有100以下的容量 ,因为最多走100次也就是最多喝100斗酒,太多了喝不完

#include<bits/stdc++.h>using namespace std;#define pair<int,int> PII#define int long longconst int mod=1e9+7;const int N=100+10;int n,m;int f[N+N][N+N][N];//f[i][j][k]表示已经走了i次,有j次经过了酒馆,还剩k斗酒signed main(){    cin>>n>>m;    f[0][0][2]=1;    for(int i=1;i<=n+m;i++)    {        for(int j=0;j<=i;j++)        {            for(int k=0;k<100;k++)            {                f[i][j][k]=(f[i][j][k]+f[i-1][j][k+1])%mod;                if(j>=1&&k%2==0)                    f[i][j][k]=(f[i][j][k]+f[i-1][j-1][k/2])%mod;            }        }    }    cout<<f[n+m-1][n][1]<<endl;    return 0;}

J砍竹子

这个没时间写了,随便写的

posted @ 2022-04-09 20:01 巴扎嘿~ 阅读(48) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员