【蓝桥杯31日冲刺】冲刺第1日

前言

  • 大家好啊,我是只会C也要参加蓝桥杯的FyHAng。蓝桥杯省赛只剩一个月的冲刺时间,如果大家觉得之前可能复习的不充分不到位,都没有关系,只要跟着我的节奏来,一个月的时间大家都来得及。接下来的一个月,我会每天持续更新三四道题目,并且提供满分题解,帮助大家-----拿省一进国赛
    今天是第一天!


一、纯质数

如果一个正整数只有 1 和它本身两个约数,则称为一个质数(又称素数)。
前几个质数是:2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, ⋅⋅⋅ 。
如果一个质数的所有十进制数位都是质数,我们称它为纯质数。例如:2,3, 5, 7, 23, 37都是纯质数,而 11,13,17,19,29,31 不是纯质数。 当然 1, 4, 3, 5 也不是纯质数。
请问,在 1 到 20210605 中,有多少个纯质数?
题目链接纯质数

这是第十二届蓝桥杯(2021)国赛的题目,希望大家一定要掌握此题,因为质数的题目在蓝桥杯的比赛中很常见,此题就是一个很好的例题。
我们来分析一下这道题目,需要满足两个条件:

  1. 这个数本身就是质数
  2. 这个数每一个数位上的数都是质数

关于质数的题解,无非就是三种方法:

  1. 暴力法
  2. 埃氏筛法
  3. 欧拉筛

今天我用第一种和第二种的方法对该题进行分析。

1、暴力法

大致思路如下:

  1. 先判断该数是否为纯质数,依次判断该数各数位上的数是否为质数,如果每一位都是质数,则进入下一步,否则pass;
  2. 再判断是否为质数。

(注:先判断是否为纯质数,再判断是否为质数,可以大大优化时间,如果反过来运行,很可能会超时哦!)

代码如下:

#include <stdio.h>
#include <stdlib.h>

int czs(int n);
int zs(int x);

int main(int argc, char *argv[])
{
  int i;
  int cnt = 0;
  for(i = 2; i <= 20210605; i++)
  {
    if(czs(i) && zs(i))
      cnt++;
  }
  printf("%d", cnt);
  return 0;
}

int zs(int x)
{
  if(x < 2)
    return 0;
  if(x != 2 && x % 2 == 0)
    return 0;
  int i;
  for(i = 2; i * i <= x; i++)
  {
    if(x % i == 0)
      return 0;
  }
  return 1;
}

int czs(int n)
{
  while(n)
  {
    int t = n % 10;
    if(t == 1 || t == 4 || t == 6 || t == 8 || t == 9 || t == 0)
      return 0;
    n = n / 10;
  }
  return 1;
}

2、埃氏筛法

算法核心:

  1. 从2开始到20210605一路往后筛,用一个p[N]数组记录是否为质数,初始化全为0。
  2. 如果当前遍历的数对应为0,则把后面所有这个数的倍数都标记为1。(例如:2可以筛掉4、6、8、10…)。
  3. 如果是1,则表示标记过,不再进行操作。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#define N 20210605
int czs(int n)
{
  while(n)
  {
    int t = n % 10;
    if(t == 1 || t == 4 || t == 6 || t == 8 || t == 9 || t == 0)
      return 0;
    n = n / 10;
  }
  return 1;
}

int p[N] = {0};
int main()
{
  int i, j;
  for(i = 2; i <= N; i++)
  {
    if(!p[i])
    {
      for(j = 2 * i; j < N; j+=i)
      {
        p[j] = 1;
      }
    }
  }

  int cnt = 0;
  for(i = 2; i <= N; i++)
  {
    if(!p[i] && czs(i))
      cnt++;
  }
  printf("%d", cnt);
  return 0;
}

二、最少砝码

你有一架天平。现在你要设计一套砝码,使得利用这些砝码可以称出任意 小于等于 N 的正整数重量。
那么这套砝码最少需要包含多少个砝码?
注意砝码可以放在天平两边。
题目链接最少砝码

输入格式
输入包含一个正整数 N。

输出格式
输出一个整数代表答案。

样例输入
7
样例输出
3
样例说明
3 个砝码重量是 1、4、6,可以称出 1 至 7的所有重量。

1 = 1;
2 = 6 − 4(天平一边放 6,另一边放 4);

3 = 4 − 1;
4 = 4;
5 = 6 − 1;
6 = 6;
7=1+6;
少于 3 个砝码不可能称出 1 至 7​ 的所有重量。

*评测用例规模与约定
对于所有评测用例
1 ≤ N ≤ 1000000000

这是第十二届蓝桥杯(2021)省赛的题目,也是很经典的贪心算法的题型。
话不多说,让我们直接来分析题目。

贪心算法

算法核心:

  • 尽可能在增加砝码时,使得砝码可称出的重量最大。

代码如下:

#include <stdio.h>
int main()
{
    long long N;
    int weight = 1;
    int count = 1;
    int total = 1;
    
    scanf ("%lld", &N);
    while (total < N)
    {
        count++;
        weight *= 3;
        total += weight;
    }
    printf ("%lld", count);
    return 0;
}

三、灌溉

小蓝负责花园的灌溉工作。
花园可以看成一个 n 行 m 列的方格图形。中间有一部分位置上安装有出水管。
小蓝可以控制一个按钮同时打开所有的出水管,打开时,有出水管的位置可以被认为已经灌溉好。
每经过一分钟,水就会向四面扩展一个方格,被扩展到的方格可以被认为已经灌溉好。即如果前一分钟某一个方格被灌溉好,则下一分钟它上下左右的四个方格也被灌溉好。
给定花园水管的位置,请问 k 分钟后,有多少个方格被灌溉好?
题目链接灌溉

输入描述
输入的第一行包含两个整数 n, m。
第二行包含一个整数 t,表示出水管的数量。
接下来 t 行描述出水管的位置,其中第 i 行包含两个数 r, c 表示第 r 行第 c 列有一个排水管。
接下来一行包含一个整数 kk。
其中,1 ≤ n , m ≤ 100,1 ≤ t ≤ 10,1 ≤ k ≤ 100。
输出描述
输出一个整数,表示答案。
输入输出样例
输入
3 6
2
2 2
3 4
1
输出
9

这是第十二届蓝桥杯(2021)模拟赛的题目,是一道很经典的模拟枚举类型的题目。

模拟

算法核心:

  • 暴力枚举啦!

代码如下:

#include<stdio.h>
#include <stdlib.h>

void jg(int x,int y);

int a[101][101];
int n, m, t, i, j, r, c, k, ans = 0;

int main(int argc, char *argv[])
{
	scanf("%d%d\n%d", &n, &m, &t);
	for(i = 1;i <= t; i++)
	{
    	scanf("%d%d", &r, &c);
    	jg(r, c);
	}
    scanf("%d", &k);
    if(k > 1)
    {
    	int num = k - 1;
        while(num--)
        {
        	for(i = 1; i <= n; i++)
        	{
				for(j = 1; j <= m; j++)
            	{
                	if(a[i][j])
                	{
                		jg(i,j);
            		}
            	}
            }
        }
    }
    for(i = 1; i <= n; i++)
    {
    	for(j = 1; j <= m; j++)
    	{
    		if(a[i][j])
    		{
    			ans++;
			}
		}
	}
	printf("%d", ans);
	return 0;
}

void jg(int x,int y)
{
	a[x][y] = 1;
	if(!a[x-1][y])
	{
		a[x-1][y] = 1;
	}
	if(!a[x+1][y])
	{
		a[x+1][y] = 1;
	}
	if(!a[x][y-1])
	{
		a[x][y-1] = 1;
	}
	if(!a[x][y+1])
	{
		a[x][y+1] = 1;
	}
}

四、总结

这次的三道题难度不是很高。希望大家可以持之以恒,如果有任何疑问,大家都可以在评论区留言,我看到都会一一回复的!

  • 新人创作不易,还望一键三连!感谢!
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值