数论之神 HYSBZ - 2219 (原根+指标+bsgs+crt+exgcd+思维)

在ACM_DIY群中,有一位叫做“傻崽”的同学由于在数论方面造诣很高,被称为数轮之神!对于任何数论问题,他都能瞬间秒杀!一天他在群里面问了一个神题: 对于给定的3个非负整数 A,B,K 求出满足 (1) X^A = B(mod 2*K + 1) (2) X 在范围[0, 2K] 内的X的个数!自然数论之神是可以瞬间秒杀此题的,那么你呢?

Input

第一行有一个正整数T,表示接下来的数据的组数( T <= 1000) 之后对于每组数据,给出了3个整数A,B,K (1 <= A, B <= 10^9, 1 <= K <= 5 * 10^8)

Output

输出一行,表示答案

Sample Input3 213 46290770 80175784 3 46290770 80175784 3333 46290770 80175784

Sample Output

 新加数组一组--2015.02.27

27 27 297Hint

 





 

题解一堆,看看别人的吧 = =

通过这题也学到了不少的东西o_O

 




  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <cmath>
  6 #include <cstdlib>
  7 #define inf 1e17
  8 #define LL long long
  9 #include <map>
 10 using namespace std;
 11 map<LL,LL> mp;
 12 struct data
 13 {
 14     LL p,c,pc;
 15 } a[100005];
 16 int num,cnt;
 17 LL f[100005];
 18 
 19 void Chai(int x)
 20 {
 21     num=0;
 22     for (int i=2; i<sqrt(x+0.5); i++) if (x%i==0)
 23         {
 24             a[++num].p=i;
 25             a[num].c=0,a[num].pc=1;
 26             while (x%i==0) x/=i,a[num].c++,a[num].pc*=i;
 27             if (x==1) break;
 28         }
 29     if (x!=1) a[++num].p=x,a[num].pc=x,a[num].c=1;
 30 }
 31 
 32 LL Pow(LL x,LL n,LL mod)
 33 {
 34     LL ans=1,b=x;
 35     while (n)
 36     {
 37         if (n&1) ans=ans*b%mod;
 38         b=b*b%mod;
 39         n>>=1LL;
 40     }
 41     return ans;
 42 }
 43 
 44 LL GetPrimitiveRoot(LL p,LL phi)
 45 {
 46     int c=0;
 47     for (int i=2; i*i<=phi; i++) if (phi%i==0) f[++c]=i,f[++c]=phi/i;
 48     for (int g=2;; g++)
 49     {
 50         int j;
 51         for (j=1; j<=c; j++) if (Pow(g,f[j],p)==1) break;
 52         if (j==c+1) return g;
 53     }
 54     return 0;
 55 }
 56 
 57 void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
 58 {
 59     if (!b)
 60     {
 61         d=a,x=1,y=0;
 62         return;
 63     }
 64     exgcd(b,a%b,d,y,x);
 65     y-=x*(a/b);
 66 }
 67 
 68 LL BSGS(LL A,LL B,LL C)
 69 {
 70     int m=ceil(sqrt(C+0.5));
 71     mp.clear();
 72     LL now=1;
 73     for (int i=1; i<=m; i++)
 74     {
 75         now=now*A%C;
 76         if (!mp[now]) mp[now]=i;
 77     }
 78     mp[1]=0;
 79     A=Pow(A,m,C);
 80     now=1LL;
 81     for (int i=0; i<=m; i++)
 82     {
 83         LL d,x,y;
 84         exgcd(now,C,d,x,y);
 85         x=(x*B%C+C)%C;
 86         if (mp.count(x)) return i*m+mp[x];
 87         now=now*A%C;
 88     }
 89     return 0;
 90 }
 91 LL Gcd(LL a,LL b)
 92 {
 93     if (!b) return a;
 94     return Gcd(b,a%b);
 95 }
 96 LL Solve(LL A,LL B,LL k)
 97 {
 98     LL phi=a[k].pc-a[k].pc/a[k].p,g=GetPrimitiveRoot(a[k].pc,phi);
 99     LL ind=BSGS(g,B,a[k].pc);
100     LL ans=Gcd(phi,A);
101     if (ind%ans) return 0;
102     return ans*Pow(a[k].p,cnt-cnt/A,inf);
103 }
104 int main()
105 {
106     int T;
107     scanf("%d",&T);
108     while (T--)
109     {
110         LL A,B,k;
111         scanf("%lld%lld%lld",&A,&B,&k);
112         LL p=2*k+1;
113         Chai(p);
114         LL ans=1;
115         for (int i=1; i<=num; i++)
116         {
117             if (!ans) break;
118             if (B%a[i].pc==0) ans=ans*Pow(a[i].p,a[i].c-(a[i].c-1)/A-1,inf);
119             else
120             {
121                 int b=B;
122                 cnt=0;
123                 while ((b%a[i].p)==0) b/=a[i].p, a[i].pc/=a[i].p, a[i].c--,cnt++;
124                 if (cnt%A) ans=0;
125                 else ans=ans*Solve(A,b,i);
126             }
127         }
128         printf("%lld\n",ans);
129     }
130     return 0;
131 }

 

转载于:https://www.cnblogs.com/zhangbuang/p/10946261.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值