zoukankan      html  css  js  c++  java
  • GCDLCM 【米勒_拉宾素数检验 (判断大素数)】

    GCDLCM

    题目链接(点击)

    题目描述

    In FZU ACM team, BroterJ and Silchen are good friends, and they often play some interesting games.
    One day they play a game about GCD and LCM. firstly BrotherJ writes an integer A and Silchen writes an integer B on the paper. Then BrotherJ gives Silchen an integer X. Silchen will win if he can find two integers Y1 and Y2 that satisfy the following conditions:
    • GCD(X, Y1) = A
    • LCM(X, Y2) = B
    • Fuction GCD(X, Y ) means greatest common divisor between X and Y .
    • Fuction LCM(X, Y ) means lowest common multiple between X and Y .
    BrotherJ loves Silchen so much that he wants Silchen to win the game. Now he wants to calculate how many number of X he can give to Silchen.

    输入

    Input is given from Standard Input in the following format:
    A B
    Constraints
    1 ≤ A, B ≤ 1018
    Both A and B are integers.

    输出

    Print one integer denotes the number of X.

    样例输入

    3 12
    

    样例输出

    3

    题意:

    给出A和B要求找到x、y1和y2满足条件的x个数:(y1和y2任意取)

    gcd (x,y1) = A

    gcd (x,y2) = B

    例如 当A=3  B=12时

    当x=3的时候满足:gcd(3,3)= 3并且 lcm(3,12)

    当x=6的时候满足:gcd(6,3)= 3并且 lcm(6,12)

    当x=6的时候满足:gcd(12,3)= 3并且 lcm(12,3)

    只有上面三种x符合条件 所以结果是 3

    思路:

    可以列出表达式或者根据上面规律可以推出:

    满足条件的 x 一定是A的倍数 并且是B的因子 也就是求B/A的因子个数(前提是A是B的倍数)

    之前解决这类问题都是素数打表+唯一分解定理解决 可是这个题的数范围太大 打表基本不可能实现

    就引入下面代码中的方法

    米勒_拉宾素数检验:

    具体推导过程和原理这个博客写的很好:

    感谢https://blog.csdn.net/qq_40564464/article/details/81774129

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int mod=1e9+7;
    LL qmul_mod(LL m,LL q,LL mod) ///快速乘 保证高精度 避免快速幂相乘爆LL
    {
        LL ans=0;
        while(q){
            if(q%2){
                ans=(ans+m)%mod;
            }
            m=(m*2)%mod;
            q/=2;
        }
        return ans;
    }
    LL qpow_mod(LL m,LL q,LL mod) ///快速幂+取模
    {
        LL ans=1;
        while(q){
            if(q%2){
                ans=qmul_mod(ans,m,mod);
            }
            m=qmul_mod(m,m,mod);
            q/=2;
        }
        return ans;
    }
    ///2 7 61
    bool Miller_Rabbin(LL x) ///米勒拉宾素数检验算法 博客里面给的是用2、3、5、7、11正确性很高 但我
    {                            ///改了那个之后会Wa没办法 可用这个就过了 顿时…
        if(x==2||x==7||x==61) return true; //肯定是素数
        if(x%2==0||x%7==0||x%61==0) return false; //素数倍数
        if(qpow_mod(2,x-1,x)==1&&qpow_mod(7,x-1,x)==1&&qpow_mod(61,x-1,x)==1) ///均满足费马小
            return true;                      ///定理说明一定是素数(从推荐的那个博客中有讲原因)
        else
            return false;
    }
    int main()
    {
        LL A,B;
        scanf("%lld%lld",&A,&B);
        if(B%A==0){
            B/=A;
            LL ans=1;
            for(int i=2;i<=1000000;i++){ ///这种方法不需要素数打表 只要跑一边for循环就可以把小于
                LL Count=0;                  ///1e6的因子除去 还挺好
                while(B%i==0){
                    Count++;
                    B/=i;
                }
                ans=ans*(Count+1)%mod;
            }
            if(B>1){ ///下面可能有点难理解 
                if(Miller_Rabbin(B)){  ///被上面的循环筛过一次之后 剩下的如果B>1 剩下的肯定是由素
                    ans=ans*2%mod;    ///数构成的数 可能是一个大素数 也可能是两个素数
                }                  ///而不可能是三个素数构成 因为三个>1e6的数相乘肯定会超1e18 
                else{
                    LL t=sqrt(B);
                    if(t*t==B) ///是两个相同的素数构成的
                        ans=ans*3%mod; 
                    else ///两个不同的素数构成的
                        ans=ans*4%mod;
                }
            }
            printf("%lld
    ",ans);
        }else
            printf("0
    ");
        return 0;
    }
    
  • 相关阅读:
    [Codechef Coders' Legacy 2018 CLSUMG]Sum of Primes
    [HDU4630]No Pain No Game
    [Luogu4329][COCI2006]Bond
    [数论]Gcd/ExGcd欧几里得学习笔记
    [数论]线性基学习笔记
    [Luogu5190][COCI2010]PROGRAM
    IIS7 HTTPS 绑定主机头,嘿嘿,转
    React
    ios
    iOS10 权限配置
  • 原文地址:https://www.cnblogs.com/ldu-xingjiahui/p/12407433.html
Copyright © 2011-2022 走看看