zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    netcat命令
    CSS 中背景图片定位方法
    Eclipse 安装svn插件及使用
    【Mysql】数据库为啥会出现_encrypt和_warning成对的表
    【Mysql异常】[HY000][1030] Got error 28 from storage engine
    【Nginx】使用certbot安装免费https证书使Nginx支持Https请求
    【Nginx】将http升级到https并且同时支持http和https两种请求
    【异常】org.eclipse.jgit.api.errors.TransportException: git@xxx.xxx.xxx/base-config-center.git: channel is not opened.
    【Spring Boot】Spring Boot之利用Logstash将日志转换成以JSON的格式存储和输出
    【Spring Cloud】Spring Cloud之Zipkin server搭建以及RabbitMQ收集,分布式服务跟踪(3)
  • 原文地址:https://www.cnblogs.com/juruolty/p/6667657.html
Copyright © 2011-2022 走看看