计蒜客2019蓝桥杯省赛A组模拟赛(一)题目及解析

先放这,等有时间再补。。。

 

A. 结果填空:阶乘位数 https://www.jisuanke.com/course/1797/162718

A题主要用到log10(N)+1就是N的位数。这个小数学知识点。然后模拟求就行了。。结果是3249,可以自己试下看看结果对不对。

#include <cstdio>
#include <string>
#include<list>
#include<cstring>
#include<iostream>
#include<cmath>
#define M 1000000
using namespace std;
int main()
{
    double ans=0;
    int flag=0;
    for(int i=1;i<=1000000;i++)
    {
        ans=0;
        for(int j=1;j<=i;j++)
        {
            ans+=log10(j*1.0);

        }
        if(ans+1>=10000)
        {
            flag=i;
            break;
        }
        //cout<<i<<"  "<<ans<<" "<<endl;
    }
    cout<<flag<<endl;
    return 0;
}

 B. 结果填空:炮台实验 题库链接
分值: 7https://www.jisuanke.com/course/1797/162719

B题的话就是组合排列数学。第一种方法就是暴力求出A!个排列,然后找规律,求到n==10;

的时候发现,期望ans=1+1/2+1/3+……1/n;

如果找不到规律怎么办呢,那我们来分析一下。

首先最高的炮台n是不会被摧毁的,一定会被留下了,对ans的贡献值是1,(概率1*炮台数1);

然后次高的炮台,放在n左边和n右边的概率一样,所以被摧毁的概率是1/2,贡献为1/2;

以此类推,可以得到。ans=ans=1+1/2+1/3+……1/n;

然后就写个模拟就行,。  在纸上想一下演算一下很快就能懂的!

#include <cstdio>
#include <string>
#include<list>
#include<cstring>
#include<iostream>
#include<cmath>
#define M 1000000
using namespace std;
int main()
{
    double ans=0;
    for(int i=1;i<=2019;i++)
        ans+=1.0/i;
    cout<<ans;
    return 0;
}

 

 

 C. 结果填空:马的管辖 题库链接
分值: 13

二进制压缩,然后直接搜索就行了。bm判断上下左右是否有蹩马腿的情况。dm是马可到达的地方。

官方题解不让放,我就自己写了个,比较适合新手阅读,大佬勿喷。。。,加了一个剪枝的地方==当马数大于最小可行方案是剪掉。时间从28S降到7S左右,非常可观。。不过这要是ACM岂不是GG。。。不愧是暴力杯~~

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int dm[8][2]={-1, -2, -1, 2, -2, -1, -2, 1, 1, -2, 1, 2, 2, -1, 2, 1};//{1,2,-1,2,2,1,2,-1,1,-2,-1,-2,-2,1,-2,-1};
int bm[8][2]={ 0, -1,  0, 1, -1,  0, -1, 0, 0, -1, 0, 1, 1,  0, 1, 0};//{0,1,0,1,1,0,1,0,0,-1,0,-1,-1,0,-1,0};
int ma[10][10];
int n,m,minn;
int check(int z)
{
    memset(ma,0,sizeof(ma));
    int cnt=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(z&1)
                ma[i][j]=1,cnt++;
            z>>=1;
        }
    if(cnt>minn)
        return -1;
   /* for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                cout<<ma[i][j]<<" ";
            puts("");
        }
    puts("");*/
   // printf("%d*****\n",cnt);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(ma[i][j]==1)
            for(int k=0;k<8;k++)
            {
                int x=i+dm[k][0],y=j+dm[k][1];
                int bx=i+bm[k][0],by=j+bm[k][1];
                if(x<1||y<1||x>5||y>5)
                    continue;
                if(ma[bx][by]==1)
                    continue;
                if(ma[x][y]==0)
                    ma[x][y]=2;
            }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(!ma[i][j])
            return -1;
    return cnt;
}
int num[28];
int main()
{
    memset(num, 0, sizeof(num));
    cin>>n>>m;
    int r=n*m;
    minn=r;
    for(int i=0;i<(1<<r);i++)
    {
        int q=check(i);
        if(q!=-1)
        {
            minn=min(q,minn);
            num[q]++;
          //  printf("%d  %d \n",q,i);
        }
    }
    for(int i=1;i<=r;i++)
    {
        if(num[i])
        printf("%d++%d\n",num[i],i);//马个数对应的方案数
    }
    return 0;
}

 

 D. 结果填空:修建公路 题库链接
分值: 17

D题有点思维难度。。实质上是找最小生成树。。

这个|是按位或,比如二进制下1001|1101==1101;对于这一题,要想道路都联通,肯定是建MIT的道路。就是每个城市只修一条道路连出到其他城市。而每次城市联通都要花费x|y>=max(x,y),y是连向的城市。观察可以发现,要想总花费最小,肯定是所有花费都等于x==max(x,y);所以总花费最小是求和0--n-1;

所以对于第i个城市,修建道路的可选城市是种类w,i编号在二进制下编码1的个数t。w==2^t-1;

这个很简单,就是要想1101这个二进制或另一个二进制的数,必须满足另一个数<=1101且,这个数的1必须在1,2,4位。

(如果在第三位是1011,或后就是1111了,就不满足条件了)。。

然后每个城市联通一个比这个城市编号小的城市,以此类推,最后都会连到编号位0的城市,肯定满足所有城市联通的。

所以这题的难度并没有那么大,直接遍历i  1-n-1,然后乘起来贡献就行了

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const ll MOD =1e9 + 7;
int main()
{
    int n;
    cin>>n;
    ll ans=1;
    for(int i=1;i<n;i++)
    {
        int k=0,r=i;
        while(r)
        {
            if(r&1)
                k++;//统计i的二进制中1的个数;
            r>>=1;
        }
        if(k)
        ans=ans*((1<<k)-1)%MOD;
        cout<<ans<<endl;
    }
    cout<<ans<<endl;
    return 0;
}

 

 E. 代码填空:欧拉函数 题库链接
分值: 9

在数论中,对正整数 n,欧拉函数  是小于等于 n 的正整数中与 n 互质的数的数目。

例如  = 4,因为 1,5,7,11 均和 12 互质。

代码框中的代码是一种求欧拉函数的实现,请分析并填写缺失的代码,计算出的值。

这一题就是根据题目分析。即使不会这个算法也可以根据题目提示做出来。

质因子分解的式子是: n=p1^k1+p2^k2+……+pr^kr;

欧拉函数值  euler(n)=p1^(k1-1)*(p1-1)+……+pr^(kr-1)*(pr-1);

可以观察到,euler(n)的值等于n*(p1-1)/p1*(p2-1)/p2*……*(pr-1)/pr;

所以枚举质因子然后每次进行*(pi-1)/pi即可。

#include <iostream>
using namespace std;
int euler(int n) {
    int res = n;
    for (int i = 2; i <= n; i++) {
        if (n % i == 0) {
            res = res - res/i;
            while (n % i == 0) {
                n /= i;
            }
        }
    }
    return res;
}
int main() {
    int n;
    cin >> n;
    cout << euler(n) << endl;
    return 0;
}

 

 F. 程序设计:掎角之势 题库链接
分值: 11

 

 G. 程序设计:轻重搭配 题库链接
分值: 19

答案:这题也和B组的一样。没看过B组的,建议先看

计蒜客2019蓝桥杯省赛B组模拟赛(一)题目及解析

 

 H. 程序设计:忽明忽暗 题库链接
分值: 21

 

 I. 程序设计:人以群分 题库链接
分值: 23

 

 J. 程序设计:势能之和 题库链接
分值: 25
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值