• BZOJ4891:[TJOI2017]龙舟(Pollard-Rho,exgcd)


    Description

    加里敦大学有一个龙舟队,龙舟队有n支队伍,每只队伍有m个划手,龙舟比赛是一个集体项目,和每个人的能力息息相关,但由于龙舟讲究配合,所以评价队伍的能力的是一个值c = (b1*b2...*bm)/(a1*a2...*am),其中bi表示第i个位置标准能力值,ai表示在队伍中第i个位置的划手的能力值。最 后通过约分,我们会得到c= B/A,其中gcd(B,A)=1,即A, B是互质的,

    但是由于比赛现场的情况不一样,我们认为在现场压力为M的情况下,队伍最后的表现情况认为是C=1(mod M)我们规定在模M的条件下1/x = y,其中y满足xy=1(mod M)并且y是大于等于0,并且小于M的值,如果不存在这 样的y我们就认为在M的条件下这支队伍会发挥失常(即y是x在模M意义下的逆元,如果不存在逆元我们认为队伍发挥失常)。现在是这个赛季的比赛安排情况,现在教练组想知道各队的在比赛中表现情况。

    Input

    第一行输入三个个整数n, m,k,表示有n支队伍,每支队伍有m个人组成,有k场比赛

    第二行输入m个整数,第i个表示表征第i个位置的标准能力值为bi

    第3行到第n +2行,共n行,每行有m个数,第2+i行第j个数表示第i支队伍的 第j个位置的划手的能力值

    第n + 3行到第n + k + 2行,共n行,每行有两个数x,M,分别表示第x支队伍 会在压力为M的比赛中出战

    Output

    共k行,第i行表示在第i个参赛安排种队伍的现场表现情况C,如果出现队伍发挥失常,输出“-1”

    Sample Input

    2 3 3
    5 2 3
    3 2 3
    2 3 2
    1 4
    2 4
    1 7

    Sample Output

    3
    -1
    4

    HINT

    对于20%的数据,1<M,ai,bi<10^8,m<=100

    对于100%的数据,1<M,ai,bi<2*10^8,m<=10000,n<=20,k<=50

    Solution

    $Pollard-Rho$。

    首先对于每次询问,先把$M$质因数分解一下,然后在分子和分母上分别用那些质因数去分解,并且开个桶存一下质因子的出现情况。如果分解完某个质因子在分母上还存在(也就是桶中的个数为负数),那显然$M$和分母不互质,无解输出$-1$。

    否则就可以用$exgcd$把逆元给解出来,然后输出就好了QwQ

    Code

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<map>
      5 #include<algorithm>
      6 #define N (10009)
      7 #define LL long long
      8 using namespace std;
      9 
     10 LL n,m,k,x,y,c,M,cnt,ans,inv;
     11 LL a[21][N],b[N],Num[N],Keg[N];
     12 LL prime[15]={2,3,5,7,11,13,17,19,23};
     13 
     14 LL Mul(LL a,LL b,LL MOD)
     15 {
     16     LL tmp=a*b-(LL)((long double)a*b/MOD+0.1)*MOD;
     17     return tmp<0?tmp+MOD:tmp;
     18 }
     19 
     20 LL Qpow(LL a,LL b,LL MOD)
     21 {
     22     LL ans=1;
     23     while (b)
     24     {
     25         if (b&1) ans=Mul(ans,a,MOD);
     26         a=Mul(a,a,MOD); b>>=1;
     27     }
     28     return ans;
     29 }
     30 
     31 LL gcd(LL a,LL b) {return b==0?a:gcd(b,a%b);}
     32 
     33 void exgcd(LL a,LL b,LL &x,LL &y)
     34 {
     35     if (!b) {x=1; y=0; return;}
     36     exgcd(b,a%b,y,x); y-=x*(a/b);
     37 }
     38 
     39 bool Miller_Rabin(LL n)
     40 {
     41     if (n==2) return 1;
     42     if (n<2 || n%2==0) return 0;
     43     LL m=n-1,l=0;
     44     while (m%2==0) m>>=1,l++;
     45     for (int i=0; i<9; ++i)
     46     {
     47         LL p=prime[i],w=Qpow(p,m,n);
     48         if (w==1 || w==n-1 || p==n) continue;
     49         for (int j=1; j<=l; ++j)
     50         {
     51             LL u=Mul(w,w,n);
     52             if (u==1 && w!=1 && w!=n-1) return 0;
     53             w=u;
     54         }
     55         if (w!=1) return 0;
     56     }
     57     return 1;
     58 }
     59 
     60 LL Pollard_Rho(LL n,LL c)
     61 {
     62     LL x=rand()%n,y=x,p=1,k=2;
     63     for (int i=1; p==1; ++i)
     64     {
     65         x=(Mul(x,x,n)+c)%n;
     66         p=x>y?x-y:y-x;
     67         p=gcd(p,n);
     68         if (i==k) y=x, k+=k;
     69     }
     70     return p;
     71 }
     72 
     73 void Solve(LL n)
     74 {
     75     if (n==1) return;
     76     if (Miller_Rabin(n)) {Num[++cnt]=n; return;}
     77     LL t=n;
     78     while (t==n) t=Pollard_Rho(n,rand()%(n-1)+1);
     79     Solve(t); Solve(n/t);
     80 }
     81 
     82 int main()
     83 {
     84     scanf("%lld%lld%lld",&n,&m,&k);
     85     for (int i=1; i<=m; ++i)
     86         scanf("%lld",&b[i]);
     87     for (int i=1; i<=n; ++i)
     88         for (int j=1; j<=m; ++j)
     89             scanf("%lld",&a[i][j]);
     90     while (k--)
     91     {
     92         for (int i=1; i<=cnt; ++i) Keg[i]=0;
     93         cnt=0; ans=1; inv=1;
     94         scanf("%lld%lld",&x,&M);
     95         Solve(M);
     96         sort(Num+1,Num+cnt+1);
     97         cnt=unique(Num+1,Num+cnt+1)-Num-1;
     98         for (int i=1; i<=m; ++i)
     99         {
    100             LL tmp=b[i];
    101             for (int j=1; j<=cnt; ++j)
    102                 while (tmp%Num[j]==0) Keg[j]++, tmp/=Num[j];
    103             ans=Mul(ans,tmp,M);
    104         }
    105         for (int i=1; i<=m; ++i)
    106         {
    107             LL tmp=a[x][i];
    108             for (int j=1; j<=cnt; ++j)
    109                 while (tmp%Num[j]==0) Keg[j]--, tmp/=Num[j];
    110             inv=Mul(inv,tmp,M);
    111         }
    112         bool flag=true;
    113         for (int i=1; i<=cnt; ++i)
    114             if (Keg[i]<0) flag=false;
    115         if (!flag) {puts("-1"); continue;}
    116         for (int i=1; i<=cnt; ++i)
    117             if (Keg[i]) ans=Mul(ans,Qpow(Num[i],Keg[i],M),M);
    118         exgcd(inv,M,x,y); inv=(x%M+M)%M;
    119         printf("%lld
    ",Mul(ans,inv,M));
    120     }
    121 }
  • 相关阅读:
    快速查看表结构(zml)
    康尼机电的发送邮件的功能2
    康尼机电的发送邮件的功能1
    8.2文件控制总览只循环了第一行
    ClientScript.RegisterStartupScript
    康尼机电的委托协议中的点击操作显示标签卡的功能
    1020 Tree Traversals (25 分)
    1017 Queueing at Bank (我自己写的模拟时间的版本)
    1016 Phone Bills ( vector的使用)
    1015 Reversible Primes
  • 原文地址:https://www.cnblogs.com/refun/p/10117580.html
Copyright © 2020-2023  润新知