【牛客网】“纽劢科技杯”第十六届同济大学程序设计竞赛暨上海邀请赛同步赛 C 半素数

链接: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;
    }
}
发布了119 篇原创文章 · 获赞 20 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_40727946/article/details/89435967