• bzoj 1951 lucas crt 费马小定理


    首先假设输入的是n,m

    我们就是要求m^(Σ(c(n,i) i|n)) mod p

    那么根据费马小定理,上式等于

    m^(Σ(c(n,i) i|n) mod  (p-1)) mod p

    那么问题的关键就是求 Σ(c(n,i) i|n) mod  (p-1)了

    那么如果P是素数的话,我们可以用lucas定理来快速求出来组合数,这道题的p-1是

    非素数,那么我们分解质因数pi,假设c(n,i) i|n为X,那我们求出来X mod pi=ai,这个是

    符合lucas定理的,那么我们可以得到质因子数个式子(本题有4个质因子),然后我们用

    中国剩余定理合并这4个式子就行了

    /**************************************************************
        Problem: 1951
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:108 ms
        Memory:540 kb
    ****************************************************************/
     
    //By BLADEVIL
    const
        d39                     =999911659;
        pp                      :array[1..4] of longint=(2,3,4679,35617);
         
    var
        n, m, k                 :int64;
        cc                      :int64;
        a                       :array[0..10] of int64;
        i                       :longint;
        fac                     :array[0..40000] of int64;
         
    function ex_gcd(a,b:int64):int64;
    var
        z                       :int64;
    begin
        if b=0 then
        begin
            ex_gcd:=1;
            cc:=0;
            exit;
        end else
        begin
            z:=ex_gcd(b,a mod b);
            ex_gcd:=cc;
            cc:=z-(a div b)*cc;
        end;
    end;    
     
    function gcd(a,p:int64):int64;
    begin
        gcd:=ex_gcd(a,p);
        gcd:=(gcd mod p+p) mod p;
    end;
         
    function combine(a,b,p:int64):int64;
    var
        ans1, ans2              :int64;
        i                       :longint;
    begin
        ans1:=fac[a] mod p;
        ans2:=(fac[a-b]*fac[b]) mod p;
        ans2:=gcd(ans2,p);
        combine:=ans1*ans2 mod p;
    end;
         
    function lucas(x,y,p:int64):int64;
    var
        a, b                    :int64;
    begin
        if y=0 then exit(1);
        a:=x mod p;
        b:=y mod p;
        if a<b then exit(0) else lucas:=lucas(x div p,y div p,p)*combine(a,b,p);
    end;    
     
    function crt:int64;
    var
        i                       :longint;
    begin
        crt:=0;
        for i:=1 to 4 do
            crt:=(crt+a[i]*((d39-1) div pp[i])*gcd((d39-1) div pp[i],pp[i])) mod (d39-1);
    end;
     
    function get(x:int64):int64;
    var
        i, j                    :longint;
    begin
            for i:=1 to trunc(sqrt(x)) do
            begin
                if x mod i=0 then
                begin
                    for j:=1 to 4 do
                    begin
                        a[j]:=(a[j]+lucas(x,i,pp[j])) mod pp[j];
                        if x div i<>i then a[j]:=(a[j]+lucas(x,x div i,pp[j])) mod pp[j];
                    end;
                end;
            end;
        get:=crt;
    end;
     
    function mi(n,k,p:int64):int64;
    var
        sum                     :int64;
    begin
        mi:=1;
        sum:=n;
        while k<>0 do
        begin
            if k mod 2=1 then mi:=mi*sum mod p;
            sum:=sum*sum mod p;
            k:=k div 2;
        end;
    end;
     
    begin
        fac[0]:=1;
        for i:=1 to pp[4] do fac[i]:=fac[i-1]*int64(i) mod (d39-1);
        read(n,m);
        if m mod d39=0 then
        begin
            writeln(0);
            halt;
        end;
        k:=get(n);
        writeln(mi(m,k,d39));
    end.
  • 相关阅读:
    Redis 发布/订阅模式
    Task
    并发入门
    ThreadPool线程池
    C# 5.0 CallerMemberName CallerFilePath CallerLineNumber获取调用方法名称,路径,行号
    信号量
    互斥体
    锁机制
    .net remoting(1)简单例子
    C#并行编程-并发集合
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3485509.html
Copyright © 2020-2023  润新知