一 纯质数(2021国赛 C++ B组)
如果一个正整数只有 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, 35也不是纯质数。请问,在 1 到 20210605 中,有多少个纯质数?
分析:此题可用都阔以想到的暴力解法,唯一注意的是要先判断数位中是否全是2或3或5或7,再判断是否是质数,必须这样的顺序,否则会超时;但是填空题的话交换了判断次序跑个几十秒也是可以跑出来的。
#include<bits/stdc++.h>
using namespace std;
bool is_prime(int x){ //判断素数,时间复杂度只有O(1/6 sqrt(N))
if( x == 1){
return false;
}
if( x==2 || x==3){
return true;
}
if(x%6!=1 && x%6 !=5){
return false;
}
int s = sqrt(x);
for(int i = 5; i <= s; i+=6){
if( x%i==0 || x%(i+2) == 0){
return false;
}
}
return true;
}
bool pure(int x){
while(x){
int t = x % 10;
if(!( t == 2 || t == 3 || t == 5 || t == 7)){
return false;
}
x /= 10;
}
return true;
}
int main()
{
int cnt = 1;
for(int i = 3 ; i <=20210605;i+=2){
if( pure(i) && is_prime(i)){
cnt++;
}
}
cout<<cnt;
return 0; //1903
}
二 最少砝码
你有一架天平。现在你要设计一套砝码,使得利用这些砝码可以称出任意 小于等于 NN 的正整数重量。
那么这套砝码最少需要包含多少个砝码?
注意砝码可以放在天平两边。
分析:主要是找规律
1以内 需要砝码1。
2,3, 4,需要 砝码1、3(=1+2) 。
5开始,至少需要砝码1、3、9(=4+5)。最多可以描述到13以内。
14开始, 至少需要1,3,9,27(=13+14) 最多可以描述到40以内。
41开始, 至少需要…27,81(=40+41),最多可以描述到121以内。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
// 主要是找规律
// 1以内 需要1
// 2,3, 4,需要 1,3(=1+2)
// 5开始,至少需要1,3,9(=4+5)。最多可以描述到13以内
// 14开始, 至少需要1,3,9,27(=13+14) 最多可以描述到40以内
// 41开始, 至少需要...27,81(=40+41),最多可以描述到121以内。
ll n;
cin>>n;
int cnt = 1, w = 1, max_w = 1;
while(1){
if(n <= max_w) break;
w *= 3;
cnt++;
max_w += w;
}
cout<<cnt;
return 0;
}
三 灌溉
小蓝负责花园的灌溉工作。
花园可以看成一个 nn 行 mm 列的方格图形。中间有一部分位置上安装有出水管。
小蓝可以控制一个按钮同时打开所有的出水管,打开时,有出水管的位置可以被认为已经灌溉好。
每经过一分钟,水就会向四面扩展一个方格,被扩展到的方格可以被认为已经灌溉好。即如果前一分钟某一个方格被灌溉好,则下一分钟它上下左右的四个方格也被灌溉好。
给定花园水管的位置,请问 kk 分钟后,有多少个方格被灌溉好?
分析:要是采用队列,依次对某一分钟该进行扩散的水管向四周扩散,最后统计多少个放个被扩散了即可。
#include <bits/stdc++.h>
using namespace std;
int garden[104][104];
struct location{
int x,y;
};
int main()
{
//主要是采用队列,依次对某一分钟该进行扩散的水管向四周扩散。
int m,n,t;
cin>>n>>m>>t;
int cnt = 0; //个数
int x, y;
queue<location> Q;
location l, l1; //l记录当前应该灌溉的水管,l1记录下一分钟要灌溉的水管,方便加入队列。
for(int i = 1; i <= t; ++i){ //初始化
cin>>x>>y;
garden[x][y] = 1;
l.x = x;
l.y = y;
Q.push(l);
}
int k;
cin>>k;
for(int p = 1; p <= k; ++p){
int s = Q.size(); //计算这一分钟有几个源头
for(int i = 0; i < s; i++){
l = Q.front();Q.pop();
if(garden[l.x-1][l.y] != 1){ //灌溉并加入队列 ,没被灌溉过才可以加入队列
garden[l.x-1][l.y] = 1;
l1.x = l.x-1;l1.y=l.y;
Q.push(l1);
}
if( garden[l.x+1][l.y] != 1){
l1.x = l.x+1;l1.y=l.y;
garden[l.x+1][l.y] = 1;
Q.push(l1);
}
if(garden[l.x][l.y-1] != 1){
l1.x = l.x;l1.y=l.y-1;
garden[l.x][l.y-1] = 1;
Q.push(l1);
}
if(garden[l.x][l.y+1] != 1){
l1.x = l.x;l1.y=l.y+1;
garden[l.x][l.y+1] = 1;
Q.push(l1);
}
}
}
for(int i = 1; i<=n;++i){
for(int j = 1; j <=m;++j){
if(garden[i][j] == 1){ //查找被灌溉的个数
cnt++;
}
}
}
cout<<cnt;
return 0;
}