• BZOJ2219 数论之神


    题意为求$x^A=B;(mod;P)$解的个数。
    把$P$分解质因数得$P=p_1^{q_1}*p_2^{q_2}*...*p_n^{q_n}$
    之后列出n个方程:$x^A=B;(mod;p_i^{q_i})$
    那么这n个方程解的个数的乘积即为原方程解的个数。
    因为我们可以从每个解集中选一个解,根据中国剩余定理,它对应了一个原方程的解,所以原方程解的个数就是每个方程解的个数的乘积。
    考虑求$x^A=B;(mod;p^a)$解的个数。
    1.
    如果$B=0$,那么$x$肯定是形如$k*p^t$的形式,其中$t$为最小的$A*t>=a$的$t$,即$lfloor{frac{a-1}A} floor+1$,解就有$p^{a-t}$个。
    2.
    如果$gcd(B,p^a)=1$,我们需要引入几个概念。
    【阶】
    阶$delta(a)$表示最小的$x>0$使得$a^x=1;(mod;p)$
    【原根】
    如果$delta(g)=varphi(p)$,则$g$是$p$的原根。
    【指标】
    指标$ind(a)$表示在模$p$意义下以$p$的原根$g$为底,$a$的对数,即$$g^{ind(a)}=a;(mod;p)$$【指标的性质】
    $a=b;(mod;p)Leftrightarrow ind(a)=ind(b);(mod;varphi(p))$
    $ind(a*b)=ind(a)+ind(b);(mod;varphi(p))$
    $ind(a^k)=k*ind(a);(mod;varphi(p))$

    那么原方程相当于$$ind(x^A)=ind(B);(mod;varphi(p))$$$$A*ind(x)=ind(B);(mod;varphi(p))$$这是一个线性方程,设$G=gcd(A,varphi(p))$,当$ind(B)\%G!=0$时无解,否则解的个数为$G$(每$frac{varphi(p)}G$有一个解,一共就有$frac{varphi(p)}{frac{varphi(p)}G}=G$个)
    3.
    如果$gcd(B,p^a)>1$,设$B$是形如$p^k*b$的形式,移项得$$p^{-k}*x^A=b;(mod;p^{a-k})$$那么如果$k\%A;!=0$,则方程无解。
    否则可以化成$$(x*p^{-frac kA})^A=b;(mod;p^{a-k})$$此时$gcd(b,p^{a-k})=1$,可以转到情况2.
    需要注意的是,此方程并不与原方程同解,因为这个方程的解的取值范围是$[0,p^{a-k+frac kA})$,而原方程的解的取值范围为$[0,p^a)$,所以最后需要乘上$p^{k-frac kA}$

    #include <cstdio>
    #include <map>
    #include <cmath>
    using namespace std;
    
    typedef long long ll;
    const int nf=0x3f3f3f3f;
    int T,a,b,p,a1,d[1000000];
    map<ll,int> mp;
    
    int gcd(int a,int b) {return b?gcd(b,a%b):a;}
    ll pw(ll a,int b,int p) {ll r=1; for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p; return r;}
    
    int bsgs(int a,int b,int p) {
        int m=ceil(sqrt(p));
        ll A=1,a1=1,A1=pw(a,m,p);
        mp.clear();
        for(int i=1;i<=m;i++) {
            A=A*a%p;
            if(!mp[A*b%p]) mp[A*b%p]=i;
        }
        for(int i=1;i<=m;i++) {
            a1=a1*A1%p;
            if(mp[a1]) return i*m-mp[a1];
        }
        return -1;
    }
    
    int sol(int A,int b,int p,int a,int pa) {
        b%=pa;
        if(!b) return pw(p,a-(a-1)/A-1,nf);
        if(gcd(b,pa)>1) {
            int tt=0;
            while(gcd(b,pa)^1) b/=p,tt++,pa/=p;
            if(tt%A) return 0;
            return sol(A,b,p,a-tt,pa)*pw(p,tt-tt/A,nf);
        }
        int fi=pa-pa/p,tt=0,g;
        for(int i=2;i*i<=fi;i++) if(fi%i==0) d[++tt]=i,d[++tt]=fi/i;
        for(g=2;;g++) {
            for(int i=1;i<=tt;i++) if(pw(g,d[i],pa)==1) goto nx;
            break;
            nx: ;
        }
        int B=bsgs(g,b,pa);
        if(!~B) return 0;
        if(B%gcd(A,fi)) return 0;
        return gcd(A,fi);
    }
    
    int main() {
        scanf("%d",&T);
        while(T--) {
            scanf("%d%d%d",&a,&b,&p),p=2*p+1,a1=1;
            for(int i=2;i*i<=p;i++) if(p%i==0) {
                int tt=0,pa=1;
                while(p%i==0) p/=i,tt++,pa*=i;
                a1*=sol(a,b,i,tt,pa);
            }
            if(p^1) a1*=sol(a,b,p,1,p);
            printf("%d
    ",a1);
        }
        return 0;
    }
  • 相关阅读:
    大数据技术(1-5题)
    如何使用不同的编程语言来造一匹马
    Redis 数据类型及应用场景
    Swoole中内置Http服务器
    redis 数据库主从不一致问题解决方案
    easyswoole对接支付宝,微信支付
    PHP+Swoole 作为网络通信框架
    基于swoole实现多人聊天室
    swoole与php协程实现异步非阻塞IO开发
    swoole中使用task进程异步的处理耗时任务
  • 原文地址:https://www.cnblogs.com/juruolty/p/6667657.html
Copyright © 2020-2023  润新知