2019杭电多校第三场 Fansblog(附带有miller robin的版本)

转自Qingo呀

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<map>
#include<string>
#include<vector>
#include<set>
#include<bitset>
#include<algorithm>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define clr(a) memset(a, 0, sizeof(a))
#define lowbit(x) x & -x
#define ls rt << 1, l, mid
#define rs rt << 1 | 1, mid + 1, r
#define PB push_back
#define POP pop_back
const double pi = acos(-1);
const int maxn = 1e5 + 101;
const int maxm = 1e7 + 101;
const ll mod = 1e9 + 7;
const int hash_mod = 19260817;

ll N, ans;
int t;
ll fast_multi(ll m, ll n, ll mod)//快速乘法
{
    ll ans = 0;//注意初始化是0,不是1
    while (n)
    {
        if (n & 1)
            ans += m;
        m = (m + m) % mod;//和快速幂一样,只不过这里是加
        m %= mod;//取模,不要超出范围
        ans %= mod;
        n >>= 1;
    }
    return ans;
}
ll fast_pow(ll a, ll n, ll mod)//快速幂
{
    ll ans = 1;
    a %= mod;
    while (n)
    {
        if (n & 1)
            ans = fast_multi(ans, a, mod);//不能直接乘
        a = fast_multi(a, a, mod);
        ans %= mod;
        a %= mod;
        n >>= 1;
    }
    return ans;
}
int cnt;
int Prime[maxm];
bool prime[maxm];
void init(){
    memset(prime, true, sizeof(prime));
    prime[0] = prime[1] = false;
    for(int i = 2 ; i < maxm ; ++ i){
        if(prime[i]) Prime[++cnt] = i;
        for(int j = 1 ; j <= cnt && i * Prime[j] < maxm ; ++ j){
            prime[i * Prime[j]] = false;
            if(i % Prime[j] == 0) break;
        }
    }
}
bool su(ll x){
    for(int j = 1 ; j <= cnt ; ++ j){
        if(x % Prime[j] == 0) return false;
    }
    return true;
}
int main()
{
    init();
    scanf("%d", &t);
    while (t--)
    {
        scanf("%lld", &N);
        ll n = N - 1;
        ans = 1;
        while(1){
            if(su(n)) break;
            //if(n <= N - 2)
            n --;
        }
        //cout << n << endl;
        //cout << ans << endl;
        for(ll i = n + 1 ; i <= N - 2 ; ++ i){
            ans = fast_multi(ans, fast_pow(i,N-2,N) % N, N);
        }
        //cout << fast_pow(ans,N-2,N) % N << endl;
        cout << ans << endl;
    }
    return 0;
}

miller robin

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<map>
#include<string>
#include<vector>
#include<set>
#include<bitset>
#include<algorithm>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define clr(a) memset(a, 0, sizeof(a))
#define lowbit(x) x & -x
#define ls rt << 1, l, mid
#define rs rt << 1 | 1, mid + 1, r
#define PB push_back
#define POP pop_back
const double pi = acos(-1);
const int maxn = 1e5 + 101;
const int maxm = 100 + 101;
const ll mod = 1e9 + 7;
const int hash_mod = 19260817;

ll N, ans;
int t;
ll fast_multi(ll m, ll n, ll mod)//快速乘法
{
    ll ans = 0;//注意初始化是0,不是1
    while (n)
    {
        if (n & 1)
            ans += m;
        m = (m + m) % mod;//和快速幂一样,只不过这里是加
        m %= mod;//取模,不要超出范围
        ans %= mod;
        n >>= 1;
    }
    return ans;
}
ll fast_pow(ll a, ll n, ll mod)//快速幂
{
    ll ans = 1;
    while (n)
    {
        if (n & 1)
            ans = fast_multi(ans, a, mod);//不能直接乘
        a = fast_multi(a, a, mod);
        ans %= mod;
        a %= mod;
        n >>= 1;
    }
    return ans;
}
ll witness(ll a, ll n)//随机生成的a,来检测n的素性
{
    ll ans = 1;
    ll t = n - 1;//这里需要注意,你如果没有改变乘方的次数的话,最后的判断就是(ans == a) ? 0 : 1;
                 // 并且还要另外开辟空间来存储开始的a,比较麻烦,所以就这样了;
    ll x;
    while (t)
    {
        if (t & 1)
        {
            ans = fast_multi(ans, a, n);
        }
        x = a;//从这里开始就是迭代乘法,验证二次验证定理
        a = fast_multi(a, a, n);//这里就相当于 x*x % m = 1
        if (a == 1 && x != 1 && x != (n - 1))
        {
            return 1; // 这里需要注意,返回一的话就说明,追踪过程中,出现了不是素数的依据.
        }
        t >>= 1;
    }
    return (ans == 1) ? 0 : 1;
}


ll MillerRobin(ll n, ll s) // 一般s取50就可以避免所有的偶然性了.
{
    if (n == 2)
    {
        return 1;
    }
    if (n < 2 || !(n & 1))
    {
        return 0;
    }
    ll a;
    for (ll i = 0; i < s; i++)
    {
        a = fast_multi((ll)rand(), n-2, 1e18+7) / RAND_MAX + 1; //这样生成的随机数就是真正的随机数了
        if (witness(a, n))
        {
            return 0;
        }
    }
    return 1;
}
int main()
{

    scanf("%d", &t);
    while (t--)
    {
        scanf("%lld", &N);
        ll n = N - 1;
        ans = 1;
        while(1){
            if(MillerRobin(n, 50)) break;
            n --;
        }
        //cout << n << endl;
        //cout << ans << endl;
        for(ll i = n + 1 ; i <= N - 2 ; ++ i){
            ans = fast_multi(ans, fast_pow(i,N-2,N) % N, N);
        }
        cout << ans << endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: RSA-CRT 算法是用于加速 RSA 密钥的模幂运算的一种方法。这种方法通过使用 Chinese Remainder Theorem(中国剩余定理)来减少计算量,从而提高效率。 下面是 RSA-CRT 算法的 Python 代码实现: ``` def rsa_crt(m: int, d: int, p: int, q: int, dp: int, dq: int) -> int: qinv = pow(q, p - 2, p) m1 = pow(m, dp, p) m2 = pow(m, dq, q) h = (qinv * (m1 - m2)) % p return m2 + h * q ``` 在这段代码中,`m` 是要解密的信息,`d` 是 RSA 私钥,`p` 和 `q` 是 RSA 密钥的两个质因数,`dp` 和 `dq` 是 RSA 私钥的两个 CRT 参数。 快速幂算法是一种用于快速计算幂的算法,它通过递归的方式来实现。递归的关键在于,对于一个数的幂,如果幂是奇数,则可以用其平方的一半再乘上它本身来得到结果;如果幂是偶数,则可以直接将幂的一半平方来得到结果。 Robin-Miller 算法是一种用于快速计算模的算法。它的基本思想是,对于一个数的模运算,如果模数是奇数,则可以将其分解成两个较小的奇数之和,然后对这两个数分别进行模运算,再将结果相加得 ### 回答2: RSA-CRT算法是一种加密算法,其中使用了两个较慢的算法:快速幂算法和Robin-Miller算法。下面是关于这两种算法的精简的Python代码实现。 1. 快速幂算法: ```python # 计算快速幂 def fast_power(base, exponent, modulus): result = 1 base = base % modulus while exponent > 0: if exponent % 2 == 1: result = (result * base) % modulus exponent = exponent // 2 base = (base * base) % modulus return result ``` 2. Robin-Miller算法: ```python # Robin-Miller素性测试 def is_prime(n, k): # 排除小于2的数和偶数 if n < 2 or n % 2 == 0: return False # 定义辅助函数 def cal_s_d(n): d = n - 1 s = 0 while d % 2 == 0: d /= 2 s += 1 return s, d # 进行k次测试 for _ in range(k): a = random.randint(2, n - 1) s, d = cal_s_d(n - 1) x = fast_power(a, d, n) if x == 1 or x == n - 1: continue for _ in range(s - 1): x = (x * x) % n if x == 1: return False if x == n - 1: break else: return False return True ``` 希望以上代码能对您有所帮助,如有任何问题,请随时告诉我。 ### 回答3: RSA-CRT算法中使用了快速幂算法和Robin-Miller算法来提高计算效率。下面是一个使用Python编写的简化代码: # 快速幂算法函数 def fast_power(base, exponent, modulus): result = 1 while exponent > 0: if exponent % 2 == 1: result = (result * base) % modulus base = (base * base) % modulus exponent = exponent // 2 return result # Robin-Miller算法函数 def robin_miller(n): # 根据Robin-Miller算法找到一个与n互质的数a a = 2 while True: if gcd(a, n) == 1: break a += 1 # 使用Robin-Miller算法进行快速判断n是否为素数 x = fast_power(a, n-1, n) if x != 1: return False else: return True # 主程序 def main(): p = 61 # 选择素数p q = 53 # 选择素数q n = p * q # 计算n euler_n = (p - 1) * (q - 1) # 计算n的欧拉函数值 # 使用Robin-Miller算法判断n是否为素数 if robin_miller(n) == False: print("n不是素数") return # 选择一个与euler_n互质的数e e = 17 # 计算e的模反元素d d = 0 while (e * d) % euler_n != 1: d += 1 # 加密 plaintext = 123 # 待加密的明文 ciphertext = fast_power(plaintext, e, n) # 加密后的密文 # 解密 decryptedtext = fast_power(ciphertext, d, n) # 解密后的明文 print("解密后的明文为:", decryptedtext) main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值