• [2019杭电多校第三场][hdu6608]Fansblog


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6608

    大致题意是比p小的最大素数q,求q!%p的值。

    由威尔逊定理开始推:

    $(p-1)!equiv-1(mod p)$

    $(p-1)!modpequiv p-1$

    $q!*(q+1)*(q+2)*...*(p-1)modpequiv p-1$

    $q!modp= frac{p-1}{(q+1)*(q+2)*...*(p-1)}modp$

    然后只需要求出q就可以了,数量级1e9的判断素数可以用Miller_Rabin判断素数。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<string>
     5 #include<cmath>
     6 #include<vector>
     7 #include<ctime>
     8 using namespace std;
     9 typedef long long ll;
    10 ll qmul(ll a, ll b, ll mod) {
    11     ll ans = 0;
    12     while (b) {
    13         if (b & 1)
    14             ans = (ans + a) % mod;
    15         a = (a << 1) % mod;
    16         b >>= 1;
    17     }
    18     return ans;
    19 }
    20 ll qpow(ll x, ll n, ll mod) {
    21     ll ans = 1;
    22     while (n) {
    23         if (n & 1)
    24             ans = qmul(ans, x, mod);
    25         x = qmul(x, x, mod);
    26         n >>= 1;
    27     }
    28     return ans;
    29 }
    30 bool Miller_Rabin(ll x) { //判断素数 
    31     srand(unsigned(time(NULL)));
    32     ll s = 0, t = x - 1;
    33     if (x == 2)  return true;   //2是素数 
    34     if (x < 2 || !(x & 1))  return false;     //如果x是偶数或者是0,1,那它不是素数 
    35     while (!(t & 1)) {  //将x分解成(2^s)*t的样子 
    36         s++;
    37         t >>= 1;
    38     }
    39     for (int i = 0; i < 10; ++i) {      //随便选10个数进行测试 
    40         ll a = rand() % (x - 1) + 1;
    41         ll b = qpow(a, t, x), k;      //先算出a^t
    42         for (int j = 1; j <= s; ++j) {    //然后进行s次平方 
    43             k = qmul(b, b, x);   //求b的平方 
    44             if (k == 1 && b != 1 && b != x - 1)     //用二次探测判断 
    45                 return false;
    46             b = k;
    47         }
    48         if (b != 1)  return false;   //用费马小定律判断 
    49     }
    50     return true;   //如果进行多次测试都是对的,那么x就很有可能是素数 
    51 }
    52 int main() {
    53     int t;
    54     scanf("%d", &t);
    55     while (t--) {
    56         ll p, q;
    57         scanf("%lld", &p);
    58         q = p - 1;
    59         while (!Miller_Rabin(q))
    60             --q;
    61         ll ans = p - 1;
    62         for (ll i = p - 1; i > q; --i)
    63             ans = qmul(ans, qpow(i, p - 2, p), p);
    64         printf("%lld
    ", ans);
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    一些内容
    ios开发 xcode6以上安装Alcatraz管理插件
    java锁的深度化-重入锁,读写锁,乐观锁,悲观锁
    并发队列
    并发工具类
    并发编程
    HashMap底层源码剖析
    双列集合map面试题
    单列集合List
    类加载
  • 原文地址:https://www.cnblogs.com/sainsist/p/11342133.html
Copyright © 2020-2023  润新知