【BZOJ】【2219】数论之神

中国剩余定理+原根+扩展欧几里得+BSGS


  题解:http://blog.csdn.net/regina8023/article/details/44863519

  新技能get√:

 1 LL Get_yuangen(LL p,LL phi){
 2     int c=0;
 3     for(int i=2;i*i<=phi;i++)
 4         if (phi%i==0)
 5             f[++c]=i,f[++c]=phi/i;
 6     for(int g=2;;g++){
 7         int j;
 8         for(j=1;j<=c;j++) if (Pow(g,f[j],p)==1) break;
 9         if (j==c+1) return g;
10     }
11     return 0;
12 }
求原根
 1 void Split(int x){
 2     num=0;
 3     for(int i=2;i*i<=x;i++)
 4         if (x%i==0){
 5             a[++num].p=i;
 6             a[num].c=0; a[num].pc=1;
 7             while(x%i==0)
 8                 x/=i,a[num].c++,a[num].pc*=i;
 9             if (x==1) break;
10         }
11     if (x!=1)
12         a[++num].p=x,a[num].pc=x,a[num].c=1;
13 }
分解一个数为$p_i^{a_i}$

 

  1 /**************************************************************
  2     Problem: 2219
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:288 ms
  7     Memory:5076 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 2219
 11 #include<cmath>
 12 #include<map>
 13 #include<cstdio>
 14 #include<cstring>
 15 #include<cstdlib>
 16 #include<iostream>
 17 #include<algorithm>
 18 #define rep(i,n) for(int i=0;i<n;++i)
 19 #define F(i,j,n) for(int i=j;i<=n;++i)
 20 #define D(i,j,n) for(int i=j;i>=n;--i)
 21 #define pb push_back
 22 using namespace std;
 23 typedef long long LL;
 24 inline int getint(){
 25     int r=1,v=0; char ch=getchar();
 26     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
 27     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
 28     return r*v;
 29 }
 30 const int N=1e5+10;
 31 const LL inf=1e18;
 32 /*******************template********************/
 33  
 34 map<LL,LL> mp;
 35 struct data{
 36     LL p,c,pc;
 37 }a[N];
 38 int num,cnt;
 39 LL f[N];
 40 void Split(int x){
 41     num=0;
 42     for(int i=2;i*i<=x;i++)
 43         if (x%i==0){
 44             a[++num].p=i;
 45             a[num].c=0; a[num].pc=1;
 46             while(x%i==0)
 47                 x/=i,a[num].c++,a[num].pc*=i;
 48             if (x==1) break;
 49         }
 50     if (x!=1)
 51         a[++num].p=x,a[num].pc=x,a[num].c=1;
 52 }
 53 LL Pow(LL a,LL b,LL p){
 54     LL r=1;
 55     for(;b;b>>=1,a=a*a%p) if (b&1) r=r*a%p;
 56     return r;
 57 }
 58  
 59 LL Get_yuangen(LL p,LL phi){
 60     int c=0;
 61     for(int i=2;i*i<=phi;i++)
 62         if (phi%i==0)
 63             f[++c]=i,f[++c]=phi/i;
 64     for(int g=2;;g++){
 65         int j;
 66         for(j=1;j<=c;j++) if (Pow(g,f[j],p)==1) break;
 67         if (j==c+1) return g;
 68     }
 69     return 0;
 70 }
 71  
 72 void exgcd(LL a,LL b,LL &d,LL &x,LL &y){
 73     if (!b) {d=a;x=1;y=0;return;}
 74     else{exgcd(b,a%b,d,y,x); y-=x*(a/b);}
 75 }
 76  
 77 LL BSGS(LL A,LL B,LL C){
 78     int m=ceil(sqrt(C+0.5));
 79     mp.clear();
 80     LL now=1;
 81     F(i,1,m){
 82         now = now*A%C;
 83         if (!mp[now]) mp[now]=i;
 84     }
 85     mp[1]=0;
 86     A=Pow(A,m,C);
 87     now=1LL;
 88     F(i,0,m){
 89         LL d,x,y;
 90         exgcd(now,C,d,x,y);
 91         x=(x*B%C+C)%C;
 92         if (mp.count(x)) return i*m+mp[x];
 93         now=now*A%C;
 94     }
 95     return 0;
 96 }
 97  
 98 LL gcd(LL a,LL b){return b ? gcd(b,a%b) : a;}
 99  
100 LL solve(LL A,LL B,LL k){
101     LL phi=a[k].pc-a[k].pc/a[k].p,
102        g=Get_yuangen(a[k].pc,phi);
103     LL ind=BSGS(g,B,a[k].pc);
104     LL ans=gcd(phi,A);
105     if (ind%ans) return 0;
106     return ans*Pow(a[k].p,cnt-cnt/A,inf);
107 }
108  
109  
110 int main(){
111 #ifndef ONLINE_JUDGE
112     freopen("2219.in","r",stdin);
113     freopen("2219.out","w",stdout);
114 #endif
115     int T=getint();
116     while(T--){
117         LL A=getint(),B=getint(),k=getint();
118         LL p=2*k+1;
119         Split(p);
120         LL ans=1;
121         F(i,1,num){
122             if (!ans) break;
123             if (B%a[i].pc==0)
124                 ans=ans*Pow(a[i].p,a[i].c-(a[i].c-1)/A-1,inf);
125             else{
126                 int b=B;
127                 cnt=0;
128                 while((b%a[i].p)==0){
129                     b/=a[i].p;
130                     a[i].pc/=a[i].p;
131                     a[i].c--,cnt++;
132                 }
133                 if (cnt % A) ans=0;
134                 else ans=ans*solve(A,b,i);
135             }
136         }
137         printf("%lld\n",ans);
138     }
139     return 0;
140 }
View Code

2219: 数论之神

Time Limit: 3 Sec  Memory Limit: 259 MB
Submit: 410  Solved: 48
[Submit][Status][Discuss]

Description

在 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 Input

3
213 46290770 80175784
3 46290770 80175784
3333 46290770 80175784

Sample Output

27
27
297

HINT

 新加数组一组--2015.02.27

Source

[Submit][Status][Discuss]
posted @ 2015-06-02 17:17  Tunix  阅读(428)  评论(0编辑  收藏  举报