题意:
对于给定的3个非负整数 A,B,K 求出满足 (1) X^A = B(mod 2*K + 1) (2) X 在范围[0, 2K] 内的X的个数
1 <= A, B <= 10^9, 1 <= K <= 5 * 10^8
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<iostream>
#include<vector>
#define N 100000
#define inf 2e9
#define LL long long
#define hn 7365768
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
using namespace std;
int pr[N],pl,ans;
bool b[N];
vector<pii> h[hn+10];
void get_p()
{
for(int i=2;i<N;i++)
{
if(b[i]==0) pr[++pl]=i;
for(int j=1;j<=pl;j++)
{
if(i*pr[j]>=N) break;
b[i*pr[j]]=1;
if(i%pr[j]==0) break;
}
}
}
int gcd(int a,int b)
{
if(b==0) return a;
return gcd(b,a%b);
}
int qmod(int a,int b,LL mmod)
{
int t=1;
while(b)
{
if(b%2) t=1ll*t*a%mmod;
b/=2;
a=1ll*a*a%mmod;
}
return t;
}
bool check(int x,int P,int phi)
{
int q=sqrt(phi);
for(int i=2;i<=q;i++)
{
if(phi%i) continue;
if(qmod(x,i,P)==1 || qmod(x,phi/i,P)==1) return 0;
}
return 1;
}
int findrt(int P,int phi)
{
for(int i=2;i;i++) if(check(i,P,phi)) return i;
}
int find(int x)
{
int k=x%hn,siz=h[k].size();
for(int i=0;i<siz;i++) if(h[k][i].first==x) return h[k][i].second;
return -1;
}
int get_ind(int x,LL P,int phi)
{
int g=findrt(P,phi),ny,q=sqrt(phi),res;
if(q*q<phi) q++;
ny=qmod(qmod(g,q,P),phi-1,P);
int t=1;
for(int i=0;i<q;i++)
{
h[t%hn].pb(mp(t,i));
t=1ll*t*g%P;
}
for(int i=0;i<=q;i++)
{
int j=find(x);
if(j!=-1) {res=i*q+j;break;}
x=1ll*x*ny%P;
}
t=1;
for(int i=0;i<q;i++)
{
h[t%hn].clear();
t=1ll*t*g%P;
}
return res;
}
int make(int a,int b,int p,int k)
{
int P=qmod(p,k,inf),phi=P/p*(p-1);
a%=phi;
b=get_ind(b,P,phi);
int d=gcd(a,phi);
if(b%d) return 0;
return d;
}
int cal(int a,int b,int p,int k)
{
int P=qmod(p,k,inf);
b%=P;
if(b==0) {int x=k/a;if(k%a) x++;return qmod(p,k-x,inf);}
int t=0;
while(b%p==0) b/=p,t++;
if(t%a) return 0;
int s=t/a;
return make(a,b,p,k-t)*qmod(p,t-s,inf);
}
void solve(int a,int b,int p)
{
ans=1;
for(int i=1;i<=pl;i++)
{
if(p==1) break;
if(p%pr[i])
{
if(pr[i]*pr[i]>p) break;
continue;
}
int k=0;
while(p%pr[i]==0) k++,p/=pr[i];
ans=ans*cal(a,b,pr[i],k);
}
if(p>1) ans=ans*cal(a,b,p,1);
printf("%d\n",ans);
}
int main()
{
get_p();
int z;scanf("%d",&z);
while(z--)
{
int a,b,p;scanf("%d%d%d",&a,&b,&p);
p=2*p+1;
solve(a,b,p);
}
return 0;
}
题解:
怎么感觉这题怪怪的
设p=2k+1
首先要知道可以p分解成
∏pkii
,把每个
pkii
当模数的解数乘起来就是答案。因为每条方程都是
x=ri(%ai)
的形式,每组解就是不同的ri。每种ri的选法拿去crt都可以得到唯一的不同的解。
对于每个
pk
如果
b=0(%pk)
是简单的
否则注意
pk
是有原根的,如果b和p互质找出
gl=b
,设
gr=x
就随便做了。。
如果不互质就有点奇怪。。
设
b=b′pt
显然此时t要是a的倍数
设
s=ta,x=x′ps
现在就是要找出
x′∈[0,pk−s]
满足
x′a=b′(%pk)
原方程是
x′apt=b′pt(%pk)
,用心感受一下雾就知道
x′∈[0,pk−t]
的解就是
x′a=b′(%pk−t)
的解
发现每个解加若干倍的
pk−t
代回原方程也是资磁的。。
于是每个解就变成了
pt−s
个解了。。
然后就做完了。。