蓝桥杯 第一届国际赛真题A-C题解

题目链接

A.仓库布局

解题思路: 对于这 n × m n\times m n×m的方格,我们如果找到了有 i i i行过道与 j j j列过道是不能放置货柜的,那么所能放置的货柜数自然是 ( n − i ) × ( m − j ) 个 (n-i)\times (m-j)个 (ni)×(mj)。那么由题意得,对于行来说,如果最后一行是放置货柜且向南的,那么这应该要改为过道。我们发现向南的货柜编号是 ( 1 + 3 x ) (1+3x) (1+3x)的,最后一行编号是 n n n,故若 ( n − 1 ) m o d    3 = = 0 (n-1)\mod 3==0 (n1)mod3==0,则最后一行为过道。那么还有的即是应该设置的过道,题目中设置 2 , 5 , 7... ( 2 + 3 x ) 2,5,7...(2+3x) 2,5,7...(2+3x)这样的编号为过道,那么我们易得行应设置的过道数为 ( n − 2 ) / 3 (n-2)/3 (n2)/3。对于列来说,由题意得 6 , 12 , 18 , . . . . 6 x 6,12,18,....6x 6,12,18,....6x这样的编号为过道,那么我们列应设置的过道数为 n / 6 n/6 n/6。故此题易解。

AC代码

/*
*blog:https://blog.csdn.net/hzf0701
*邮箱:unique_powerhouse@qq.com
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*/
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)

using namespace std;

typedef long long ll;
const int maxn=1e5;//数组所开最大值
const int mod=1e9+7;//模
const int inf=0x3f3f3f3f;//无穷大

ll m,n;
void solve(){
    //在行中,1,4,7,10...这种,如果n是符合这种规律的行,就必须撤除。同时,在行中若为2,5,8,11,这种都是过道。在列中,6的倍数都是过道。
    //则题易得:先计算有多少未去掉的行,再计算有多少去掉的列。
    ll temp1,temp2=  0;
    if(n!=1){
        //1这种情况没有过道。我们需要排除。
        temp1 = (n-2)/3+1;//计算有多少过道。
    }
    if((n-1)%3==0){
        temp1++;//说明最后一行要撤除。
    }
    temp2 = m/6;//计算有多少个6的倍数。
    //接下来先计算有多少个行,再*(m-去掉的列)。这即是可放置货柜的数量。
    cout << (n-temp1)*(m-temp2)<<endl;
}
int main(){
    while(cin>>n>>m){
        solve();
    }
    return 0;
}

B.网站扩张

解题思路: 这道题我们很容易就想到用递归去解题,这样做虽然是正确的,但很容易就爆栈,跑不出来结果。那么,我们应该怎样来看待这样一道题呢?我们可以把每一天都看成一个状态,这个状态值我们可以设为在这一天新的被邀请的用户总数。那么我们接下来要做的事情就比较少了,遍历每一天,统计每一天的新用户数,更新这一天的用户数在接下的天数里生成的用户数(我们只需要在接下来的状态里加就行,这方便了许多)。那么统计的用户总数即是最后的用户总数。我们这样做的好处是什么呢?我们避免了依次计算,而用天来划分,在这一天都可以邀请用户的同时邀请,同时我们避免了递归,采用天数模拟的方式去解决。详见代码,附有注释。

AC代码

/*
*blog:https://blog.csdn.net/hzf0701
*邮箱:unique_powerhouse@qq.com
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*/
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)

using namespace std;

typedef long long ll;
const int maxn=1e5;//数组所开最大值
const int mod=1e9+7;//模
const int inf=0x3f3f3f3f;//无穷大

ll dp[1000],n;
void solve(){
    memset(dp,0,sizeof(dp));
    //暴力模拟,把每一天都看成一个状态,dp[i]则表示第i天诞生的新用户。从第一天到最后一天开始遍历,统计新用户数量则是最后的结果。
    ll sum = 0;//统计这些天的用户数。
    dp[1]=1;//第一天新用户数为1.
    for(ll i=1;i<=n;i++){
        sum+=dp[i];
        if(dp[i]){
            //说明这一天存在dp[i]个新用户,我们去模拟他们在接下来的这几天邀请的用户.注:有dp[i]个新用户就接下来会邀请dp[i]个新用户。
            for(ll j=i+7;j<=n;j+=3){
                //新用户诞生。
                dp[j]+=dp[i];
            }
        }
    }
    cout<<sum<<endl;
}
int main(){
    while(cin>>n){
        solve();
    }
    return 0;
}

C.基因配对

解题思路: 这道题实际是就是字符串匹配问题,在现版本的各种语言,基本上都有find函数来实现,而不用我们自己写。这里采用的是C++String类内置的find函数,其返回值即是最早配对的位置。

AC代码

/*
*blog:https://blog.csdn.net/hzf0701
*邮箱:unique_powerhouse@qq.com
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*/
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)

using namespace std;

typedef long long ll;
const int maxn=1e5;//数组所开最大值
const int mod=1e9+7;//模
const int inf=0x3f3f3f3f;//无穷大

string L,S;
void solve(){
    //该题直接先转换,再利用string内置的find函数来查找即可。
    rep(i,0,L.size()-1){
        if(L[i]=='A'){
            L[i]='T';
        }
        else if(L[i]=='T'){
            L[i]='A';
        }
        else if(L[i]=='C'){
            L[i]='G';
        }
        else{
            L[i]='C';
        }
    }
    if(L.find(S)!=L.npos){
        cout<<L.find(S)+1<<endl;
    }
    else{
        cout<<0<<endl;
    }
}
int main(){
    while(cin>>L>>S)
        solve();
    return 0;
}

posted @ 2022-03-26 16:49  unique_pursuit  阅读(48)  评论(0)    收藏  举报