• 【bzoj2219-数论之神】求解x^a==b(%n)-crt推论-原根-指标-BSGS


    http://www.lydsy.com/JudgeOnline/problem.php?id=2219

    弄了一个晚上加一个午休再加下午一个钟。。终于ac。。TAT

    数论渣渣求轻虐!!

     

    题意:求解 x^A=B(mod n) 在0~n内解的个数。其中1 <= A, B <= 10^9, 1 <= K <= 5 * 10^8  (n=2*K+1)

    首先先说这一题的弱化版:bzoj1319 http://www.lydsy.com/JudgeOnline/problem.php?id=1319

    bzoj1319这题是保证了P为质数

    找到p的一个原根g,因为g^x构成一个缩系,g^x可以表示0~p-1所有数。
    g^j=a(%p), g(%p)=1, (g^i)^k=1(%p)
    g^ik=g^j (%p)
    ik=j(%phi(p))
    用BSGS求出j,exgcd求出所有i,x就是g^i。

     

    分析这一题:P不一定是质数。

    取模数不是质数,无法利用通常的方式解方程;

    但是有中国剩余定理这个东西,定理的推论告诉我们:

    一个取模数互质的同余方程组(未必线性),组合起来之后,这个同余方程解的个数为各方程解的个数的乘积

     

    (组合起来的方程的取模数为所有数的积;实际上这里解的范围都是属于[0 ,自己取模数) )

     

    这点十分重要呢,它不仅证明了解的求法,而且如果有任意一个方程无解,那么整个就都是无解的;

    ————引用自http://blog.csdn.net/ww140142/article/details/47814003

     

    把n分解质因数。

    接下来我们只需要处理方程x^A==B(%p^a)

    再次引用题解。。只有第三种情况是我自己搞的。。

    引用自大牛http://blog.csdn.net/regina8023/article/details/44863519

     

    但是第三种情况我没看懂它怎么搞。。

    这个时候就可以用bzoj1319的解法了!

    找到p^a的一个原根g,因为g^x构成一个缩系,g^x可以表示0~p^a-1所有数。

    有一个推论(我也不知道为什么)g是p的原根,则g是p^a的原根。就可以很快找出来啦。

    解释一下情况1和情况2为什么范围扩大之后就直接乘:

    例如情况1:t=(a-1)/A+1,[0,p^t]中有一个解,范围[0,p^a)中有p^(a-t)个这样的范围。

    假设p^t就是解。那下一个小区间中的p^(2t)也是解,以此类推。

     

    PS:找原根的方法:

    1 预判n有没有原根,有原根的数为:124、P^a,2*P^a,P为任意奇素数
    2 
    3 快速求所有原根:
    4 m=phi(n)
    5 找到m所有的质因子y
    6 找出n最小的原根a:gcd(a,n)==1 && a^(m/y) %n都!=1
    7 则a^x%n(1<=x<m,gcd(x,m)==1) 是n所有原根。

    依照上题,化成

    g^ik=g^j (%p^a)
    ik=j(%phi(p^a))
    用BSGS求出j,解i的个数就是答案。

     

    这里又有一个可爱的推论。。我还是不知道为什么。。

    ax-py=gcd(a,p)

    解的个数为gcd(a,p)。

    然后这题就做完了。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<algorithm>
      7 using namespace std;
      8 
      9 typedef long long LL;
     10 const LL N=100100,Inf=(LL)1e12;
     11 struct node{LL d,id;}num[N];
     12 LL nl,fl,pxl,px[N],r[N],f[N];
     13 
     14 void find_px(LL n)
     15 {
     16     pxl=0;
     17     for(LL i=2;i*i<=n;i++)
     18     {
     19         if(n%i==0) px[++pxl]=i,r[pxl]=0;
     20         while(n>1 && n%i==0) n/=i,r[pxl]++;
     21         if(n==1) break;
     22     }
     23     if(n>1) px[++pxl]=n,r[pxl]=1;//debug
     24 }
     25 
     26 LL gcd(LL a,LL b)
     27 {
     28     if(b==0) return a;
     29     return gcd(b,a%b);
     30 }
     31 
     32 LL quickpow(LL x,LL y,LL n)
     33 {
     34     LL ans=1%n;
     35     while(y)
     36     {
     37         if(y&1) ans=(ans*x)%n;
     38         x=(x*x)%n;y>>=1;
     39     }
     40     return ans;
     41 }
     42 
     43 bool cmp(node x,node y){
     44     if(x.d!=y.d) return x.d<y.d;
     45     return x.id<y.id;
     46 }
     47 
     48 LL find_j(LL t)
     49 {
     50     LL l=0,r=nl,mid;
     51     while(l<=r)
     52     {
     53         mid=(l+r)>>1;
     54         if(num[mid].d==t) return num[mid].id;
     55         if(num[mid].d<t) l=mid+1;
     56         if(num[mid].d>t) r=mid-1;
     57     }
     58     return -1;
     59 }
     60 
     61 LL BSGS(LL a,LL b,LL n,LL phi)//a^x==b(%n)
     62 {
     63     LL m,x,am,now,t;
     64     m=(LL)ceil(sqrt((double)n));
     65     x=1%n;
     66     nl=0;num[++nl].d=1,num[nl].id=0;
     67     for(int i=1;i<=m;i++)
     68     {
     69         x=(x*a)%n;
     70         num[++nl].d=x;num[nl].id=i;
     71     }
     72     am=x;
     73     sort(num+1,num+1+nl,cmp);
     74     now=1;
     75     for(int i=2;i<=nl;i++)
     76     {
     77         if(num[i].d!=num[i-1].d) num[++now]=num[i];        
     78     }
     79     nl=now;
     80     am=quickpow(am,phi-1,n);
     81     t=b%n;
     82     for(int i=0;i<=m;i++)
     83     {
     84         x=find_j(t);
     85         if(x!=-1) return i*m+x;
     86         t=(t*am)%n;
     87     }
     88     return -1;
     89 }
     90 
     91 LL find_root(LL p)
     92 {
     93     LL x=p-1;
     94     fl=0;
     95     for(int i=2;i*i<=p-1;i++)
     96     {
     97         if((p-1)%i==0) f[++fl]=i,f[++fl]=(p-1)/i;//debug不是找质因子啊。。
     98     }
     99     for(int i=2;i<p-1;i++)
    100     {
    101         bool bk=1;
    102         for(int j=1;j<=fl;j++)
    103             if(quickpow(i,(p-1)/f[j],p)==1) {bk=0;break;}
    104         if(bk) return i;
    105     }
    106 }
    107 
    108 LL solve_3(LL A,LL B,LL p,LL a)
    109 {
    110     LL phi,g,gc,j,pa;
    111     pa=quickpow(p,a,Inf);
    112     phi=(p-1)*quickpow(p,a-1,Inf);
    113     g=find_root(p);
    114     j=BSGS(g,B,pa,phi);
    115     gc=gcd(A,phi);
    116     // printf("phi = %lld  j = %lld g = %lld pa = %lld
    ",phi,j,g,pa);
    117     // printf("s3 %lld %lld %lld %lld = %lld
    
    ",A,B,p,a,gc);
    118     if(j%gc) return 0;
    119     return gc;
    120 }
    121 
    122 LL solve(LL A,LL B,LL p,LL a)
    123 {
    124     LL g,pa,x,y,b,cnt;
    125     pa=quickpow(p,a,Inf);
    126     g=gcd(pa,B);
    127     //case 1
    128     if(B%pa==0) return quickpow(p,a-(((a-1)/A)+1),Inf);
    129     //case 2
    130     if(g>1) 
    131     {
    132         b=B/g;
    133         cnt=0;x=g;
    134         while(x%p==0) x/=p,cnt++;
    135         if(cnt%A) return 0;
    136         return solve_3(A,b,p,a-cnt)*quickpow(p,cnt-(cnt/A),Inf);
    137     }
    138     //case 3
    139     return solve_3(A,B,p,a);
    140 }
    141 
    142 int main()
    143 {
    144     freopen("a.in","r",stdin);
    145     // freopen("me.out","w",stdout);
    146     int T;
    147     scanf("%d",&T);
    148     LL A,B,n,ans;
    149     while(T--)
    150     {
    151         scanf("%lld%lld%lld",&A,&B,&n);
    152         n=2*n+1;
    153         find_px(n);
    154         ans=1;
    155         for(LL i=1;i<=pxl;i++)
    156         {
    157             ans*=solve(A,B,px[i],r[i]);
    158             if(ans==0) break;
    159         }
    160         printf("%lld
    ",ans);
    161     }
    162     return 0;
    163 }

     

     

  • 相关阅读:
    洛谷P2414 阿狸的打字机
    洛谷P4362 贪吃的九头龙
    洛谷P4198 楼房重建
    JSP九大对象
    关于ErrorPage
    通过自己制作网页解决几个简单问题的方法
    九项重要的职业规划提示(转自W3School )
    jquery 使用方法(转载)
    <script language = "javascript">, <script type = "text/javascript">和<script language = "application/javascript">(转)
    微软当年的浏览器之战
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5853816.html
Copyright © 2020-2023  润新知