zoukankan      html  css  js  c++  java
  • 2019HDU多校第三场F Fansblog——威尔逊定理&&素数密度

    题意

    给定一个整数 $P$($10^9 leq pleq 1^{14}$),设其前一个质数为 $Q$,求 $Q!  \% P$.

    分析

    暴力...说不定好的板子能过。

    根据威尔逊定理,如果 $p$ 为质数,则有 $(p-1)! equiv p-1(mod p)$.

    $displaystyle Q! = frac{(P-1)!}{(Q+1)(Q+2)...(p-1)} equiv  (p-1)*inv (mod P)$.

    根据素数定理,$displaystyle pi (x) sim frac{x}{lnx}$,其中 $pi (x)$ 表示不超过 $x$ 的素数的个数。直观的看,$x$ 越大,素数密度越大,接近线性。

    在题给的范围,两个相邻素数通常只隔几十个数。

    为了快速找到前一个质数,这里使用了Miller-Rabin素数测试算法(虽然题目 $sqrt n$ 也能过

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long int ll;
    
    ll mod_mul(ll a, ll b, ll mod)
    {
        ll res = 0;
        while (b)
        {
            if (b & 1)
                res = (res + a) % mod;
            a = (a + a) % mod;
            b >>= 1;
        }
        return res;
    }
    
    ll mod_pow(ll a, ll n, ll mod)
    {
        ll res = 1;
        while (n)
        {
            if (n & 1)
                res = mod_mul(res, a, mod);
            a = mod_mul(a, a, mod);
            n >>= 1;
        }
        return res;
    }
    
    // Miller-Rabin随机算法检测n是否为素数
    bool Miller_Rabin(ll n)
    {
        if (n == 2)
            return true;
        if (n < 2 || !(n & 1))
            return false;
        ll m = n - 1, k = 0;
        while (!(m & 1))
        {
            k++;
            m >>= 1;
        }
        for (int i = 1; i <= 10; i++)  // 20为Miller-Rabin测试的迭代次数
        {
            ll a = rand() % (n - 1) + 1;
            ll x = mod_pow(a, m, n);
            ll y;
            for (int j = 1; j <= k; j++)
            {
                y = mod_mul(x, x, n);
                if (y == 1 && x != 1 && x != n - 1)
                    return false;
                x = y;
            }
            if (y != 1)
                return false;
        }
        return true;
    }
    
    ll mul(ll a, ll b, ll p)
    {
        ll res = 1;
        for(ll i = a;i <= b;i++)  res = mod_mul(res, i, p);
        return res;
    }
    
    ll p, q;
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%lld", &p);
            q = p-1;
            while(!Miller_Rabin(q))  q--;
            ll inv = mod_pow(mul(q+1, p-1, p), p-2, p);
            ll ans = mod_mul(p-1, inv, p);
            printf("%lld
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    HDU 5273 Dylans loves sequence 暴力递推
    HDU 5285 wyh2000 and pupil 判二分图+贪心
    HDU 5281 Senior's Gun 贪心
    HDU 5651 xiaoxin juju needs help 逆元
    HDU 5646 DZY Loves Partition
    HDU 5366 The mook jong
    HDU 5391Z ball in Tina Town 数论
    HDU 5418 Victor and World 允许多次经过的TSP
    HDU 5642 King's Order dp
    抽屉原理
  • 原文地址:https://www.cnblogs.com/lfri/p/11273277.html
Copyright © 2011-2022 走看看