链接:https://ac.nowcoder.com/acm/contest/637/C
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
最近张老师对半素数感兴趣。半素数(semi-prime)是可以表示成两个素数乘积的数。比如4和10是半素数,因为4=2×2,10=2×5。而8不是半素数,因为8=2×2×2。他想知道某一个l到r的闭区间内有多少个这样的数。但是这个问题太困难了,他想让你帮他解决。
输入描述:
输入一行,包含两个数l,r(1<=l<=r<=1010,r-l<=105),表示所求闭区间
输出描述:
第一行一个数n,表示一共有多少个半素数。
后面跟n行,每行三个整数pi ai bi,表示pi是半素数,是两个素数ai和bi的乘积
输出的n个半素数按照递增的顺序。对于每一行,ai<=bi
示例1
输入
1 10
输出
4
4 2 2
6 2 3
9 3 3
10 2 5
题解:打1e5的素数表,枚举每个素数的 j 倍,判断是否在区间内即可。
判断一个数 j 是否是素数,使用 Miller_Rabin 算法。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
ll prime[maxn];
ll visit[maxn];
//unordered_map<ll,ll> map1;
//map<ll,ll> map1;
struct HashMap //拉链法hash表
{
static const int MXSZ = 1e7 + 20; //元素总数 查询也会创建元素 能开大就开大
static const int MOD = 1e7 + 19; //1e3+9 1e4+7 1e6+3 1e7+19 1e8+7
struct node
{
ll key;
ll val, nxt;
}elem[MXSZ];
int head[MOD], tot;
void Init() //注意初始化!!!
{
tot = 0;
memset(head, -1, sizeof(head));
}
ll& operator [] (ll key)
{
int k = key % MOD; //取模位置
for (int i = head[k]; ~i; i = elem[i].nxt)
if (elem[i].key == key) //key相等
return elem[i].val; //返回val引用
elem[tot].key = key, elem[tot].nxt = head[k], head[k] = tot; //新建项 将原有的接在当前后并记录当前
return elem[tot++].val = 0; //清空值并返回引用
}
}map1;
struct node
{
ll x,y,sun;
}s[maxn];
bool cmp(node a,node b)
{
return a.sun<b.sun;
}
void Prime()
{
int cnt=0;
memset(prime,0,sizeof(prime));
memset(visit,0,sizeof(visit));
for(ll i = 2;i<=maxn;i++)
{
if (!visit[i])
{
prime[cnt++] = i;
}
for (ll j = 0; j < cnt && i*prime[j] <= maxn; j++)
{
visit[i*prime[j]] = 1;
if (i % prime[j] == 0)
{
break;
}
}
}
}
ll prime1[6] = {2, 3, 5, 233, 331};
ll qmul(ll x, ll y, ll mod)
{
return (x * y - (long long)(x / (long double)mod * y + 1e-3) *mod + mod) % mod;
}
ll qpow(ll a, ll n, ll mod) {
ll ret = 1;
while(n) {
if(n & 1) ret = qmul(ret, a, mod);
a = qmul(a, a, mod);
n >>= 1;
}
return ret;
}
bool Miller_Rabin(ll p) {
if(p < 2) return 0;
if(p != 2 && p % 2 == 0) return 0;
ll s = p - 1;
while(! (s & 1)) s >>= 1;
for(int i = 0; i < 5; ++i) {
if(p == prime1[i]) return 1;
ll t = s, m = qpow(prime1[i], s, p);
while(t != p - 1 && m != 1 && m != p - 1) {
m = qmul(m, m, p);
t <<= 1;
}
if(m != p - 1 && !(t & 1)) return 0;
}
return 1;
}
int main()
{
map1.Init();
Prime();
ll l,r;
cin>>l>>r;
int sum=0;
for(ll i=0;prime[i]*prime[i]<=r;i++)
{
for(ll j=(l/prime[i]);prime[i]*j<=r;j++)
{
if(map1[j*prime[i]]==1)
{
continue;
}
if(prime[i]*j>=l&&Miller_Rabin(j))
{
s[sum].x=prime[i];
s[sum].y=j;
s[sum].sun=prime[i]*j;
map1[j*prime[i]]=1;
sum++;
}
}
}
sort(s,s+sum,cmp);
cout<<sum<<endl;
for(int i=0;i<sum;i++)
{
cout<<s[i].sun<<" "<<s[i].x<<" "<<s[i].y<<endl;
}
}