米勒拉宾模板Palindromic Primes

Posted biu~跃哥冲冲冲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了米勒拉宾模板Palindromic Primes相关的知识,希望对你有一定的参考价值。

Problem: J . Palindromic Primes


记录个模板。
题目大意:
L L L R R R 之间既是素数又是回文数的个数。

解题思路:
数据范围 1 e 12 1e12 1e12。一般的前缀和做法解决不了。分析一下,对于一个回文数,都可以按位拆分成两部分。例如 123321 123321 123321,可以拆分为 123 123 123 321 321 321 ,对于奇数位的整数12321,可以拆分为 123 123 123 21 21 21,事实上,我们只要知道前半部分,后半部分就可以求出来,然后将前后两部分再凑到一起,判断其是否是素数即可。这样一来,对于庞大的 1 e 12 1e12 1e12 的范围,我们只需要枚举前 1 e 6 1e6 1e6个数,就可以将 1 e 12 1e12 1e12 内所有的回文整数找出来了。
接下来只剩下判断素数了,怎样快速判断一个较大的数是否是素数呢?这里用到了一个稀奇古怪的算法米勒拉宾算法
这里我就直接借模板一用啦。

AcCoding:

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll qmul(ll a, ll b, ll p)
{
    ll c = (long double)a / p * b;
    ll res = (ull)a * b - (ull)c * p;
    return (res + p) % p;
}

ll qpow(ll x, ll y, ll p)
{
    ll res = 1;
    while (y) {
        if (y & 1) res = qmul(res, x, p);
        x = qmul(x, x, p);
        y >>= 1;
    }
    return res;
}
bool isprime(ll x)
{
    if (x < 3) return x == 2;
    if (!(x & 1)) return false;
    ll A[] = { 0, 2, 325, 9375, 28178, 450775, 9780504, 1795265022 };
    ll d = x - 1, r = 0;
    while (d % 2 == 0)
    {
        r++;
        d /= 2;
    }
    for (auto a : A)
    {
        ll v = qpow(a, d, x);
        if (v <= 1 || v == x - 1) continue;
        for (int i = 1; i <= r; i++)
        {
            v = qmul(v, v, x);
            if (v == x - 1 && i != r)
            {
                v = 1;
                break;
            }
            if (v == 1)
                return false;
        }
        if (v != 1)
            return false;
    }
    return true;
}
void get(ll x,ll& sum1,ll& sum2) {
    vector<int> v;
    while (x) {
        v.push_back(x % 10);
        x /= 10;
    }
    sum1 = 0;
    sum2 = 0;
    //123
    reverse(v.begin(), v.end());
    for (int i = 0;i < v.size();i++) sum1 = sum1 * 10ll + v[i], sum2 = sum2 * 10ll + v[i];
    for (int i = v.size() - 2;i >= 0;i--) sum1 = sum1 * 10ll + v[i];
    for (int i = v.size() - 1;i >= 0;i--) sum2 = sum2 * 10ll + v[i];
}
int main() {
	ll l, r; scanf("%lld%lld", &l, &r);
    ll res = 0;
    for (ll i = 1;i <= 1000000;i++) {
        ll x, y;
        x = y = 0;
        get(i, x, y);
        if (min(x, y) > r) break;
        if (x >= l && x <= r && isprime(x)) res++;
        if (y >= l && y <= r && isprime(y)) res++;
    }
    printf("%lld", res);
	return 0;
}

以上是关于米勒拉宾模板Palindromic Primes的主要内容,如果未能解决你的问题,请参考以下文章

米勒拉宾模板Palindromic Primes

HDU2138 & 米勒拉宾模板

Python 中的 AKS Primes 算法

Miller_Rabin(米勒拉宾)素数测试

求pascal判断素数的米勒拉宾算法

HDU 2138 How many prime numbers (判素数,米勒拉宾算法)