B4158 [BCSP-X 2024 12 月小学高年级组] 质数补全 - 洛谷
思路1:线性筛,字符串匹配,枚举
质数筛选
要解决这个问题,首先得找出指定范围内(这里是 1 到 10000000)的所有质数。常用的质数筛选算法有埃拉托斯特尼筛法(埃氏筛)和欧拉筛法(线性筛),本题建议采用的是欧拉筛法,其时间复杂度为 O(n),具体步骤如下:
- 初始化一个布尔类型的数组
vis
,用于标记每个数是否为质数。把vis[0]
和vis[1]
标记为非质数(因为 0 和 1 不是质数)。 - 从 2 开始遍历到 10000000,对于每个数
i
:- 若
vis[i]
为false
,说明i
是质数,将其存储到质数数组(第一段代码是prime
数组,第二段代码是primes
向量)中。 - 遍历已找到的质数,将
i
与这些质数的乘积标记为非质数。若i
能被当前质数整除,就停止内层循环,这能保证每个合数只被其最小质因数筛去一次,从而实现线性时间复杂度。
- 若
字符串匹配判断
在找出所有质数后,需要判断输入的带有 *
通配符的字符串是否能与某个质数匹配。可以定义一个判断函数具体步骤如下:
- 首先检查两个字符串的长度是否相同,若不同则直接返回
false
。 - 接着遍历两个字符串的每个字符:
- 若对应位置的字符相同,继续检查下一个字符。
- 若输入字符串中对应位置的字符是
*
,表示该位置可以匹配任意字符,继续检查下一个字符。 - 若对应位置的字符既不相同,输入字符串中对应位置的字符也不是
*
,则返回false
。
- 若遍历完所有字符都没有返回
false
,则返回true
。
代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
bool vis[10000005];
int n;
vector<int> primes;void euler(){vis[0]=vis[1]=true;for(int i=2;i<=10000000;++i){if(!vis[i])primes.push_back(i);for(int j=0;j<primes.size()&&i*primes[j]<=10000000;++j){vis[i*primes[j]]=true;if(i%primes[j] == 0) break;}}
}bool check(string a,string b){if(a.size()!=b.size())return false;for(int i=0;i<a.size();++i){if(a[i]!=b[i]&&b[i]!='*')return false;}return true;
}int main(){int n;cin>>n;euler();while(n--){string s;cin>>s;bool flag = false;for(auto i:primes){if(check(to_string(i),s)){cout<<i<<endl;flag = true;break;}}if (!flag) cout<<"-1"<<endl;}return 0;
}