数论好题,总算把数论这一块遗漏的知识补齐了
题解传送:
http://blog.csdn.net/regina8023/article/details/44863519
http://blog.csdn.net/popoqqq/article/details/41595187
1.【阶】
满足
ax≡1(modp)
的最小的
x
是
a
关于
p
的阶。
记作
δ(a)=x
2.【原根】
若
δ(g)=φ(p)
,则称
g
是
p
的原根。
(1)只有 1,2,4,pk,2∗pk ( p 是奇素数)有原根。
(2)
p
的原根个数为
φ(φ(p))
(证明见这里)
(3)
p>1
,
φ(p)
所有不同的因数为
p1,p2,…,pk
,
(g,m)=1
,则
g
是模
p
的原根的充要条件是:
gpi≡1(modp)
对于所有的
pi
都不成立
(这也是原根的求法)
3.【指标】
若
gr≡a(modp)
成立,则称
r
是以
g
为底的
a
对模
m
的一个指标。
记作
r=inda
(1) a≡b(modp)⇔inda≡indb(modφ(p))
(2) ind(a∗b)≡inda+indb(modφ(p))
(3) ind(an)≡n∗inda(modφ(p))
(4)指标的求法:
先求出
p
的原根
g
,然后用BSGS求出
ga≡b(modp)
中的
a
(BSGS详见这里)
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
typedef pair<ll,ll> abcd;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(ll &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline int write(ll x,char c)
{
if (x==0) return putchar('0'),putchar(c),0;
if (x<0) putchar('-'),x=-x;
char s[50]={0},len=0;
while (x) s[++len]=x%10+'0',x/=10;
for (int i=len;i;i--) putchar(s[i]); putchar(c);
}
inline ll Pow(ll a,ll b,ll p)
{
ll ret=1;
for (;b;(a*=a)%=p,b>>=1)
if (b&1)
(ret*=a)%=p;
return ret;
}
inline abcd EXGCD(ll a,ll b)
{
abcd ret;
if (a<b) { ret=EXGCD(b,a); return abcd(ret.second,ret.first); }
if (!b) return abcd(1,0);
ret=EXGCD(b,a%b);
return abcd(ret.second,ret.first-a/b*ret.second);
}
namespace BSGS{
struct hashmap{
#define MOD 10007
ll num;
ll key[1000005],value[1000005],next[1000005];
ll head[MOD];
inline void insert(ll k,ll v)
{
ll ad=k%MOD;
key[++num]=k; value[num]=v; next[num]=head[ad];
head[ad]=num;
}
inline ll operator[](ll k)
{
ll ad=k%MOD;
for (int p=head[ad];p;p=next[p])
if (key[p]==k)
return value[p];
return -1;
}
inline void clear()
{
cl(head); num=0;
}
}M;
inline ll Solve(ll A,ll B,ll P,ll phi)
{
M.clear();
A%=P;
if (!A && !B) return 1;
if (!A) return -1;
ll m=sqrt((double)P)+1,tmp=1;
M.insert(1,0);
for (int i=1;i<m;i++)
{
(tmp*=A)%=P;
if (M[tmp]==-1)
M.insert(tmp,i);
}
ll inv=1,T=Pow(A,phi-m,P);
for (int k=0;k<m;k++)
{
ll i=M[B*inv%P];
if (i!=-1)
return k*m+i;
(inv*=T)%=P;
}
return -1;
}
}
ll f[1000005];
inline ll GetRoot(ll p,ll phi)
{
int c=0;
for (int i=2;i*i<=phi;i++)
if (phi%i==0)
f[++c]=i,f[++c]=phi/i;
for (int g=2;g<p;g++)
{
int j;
for (j=1;j<=c;j++)
if (Pow(g,f[j],p)==1)
break;
if (j==c+1) return g;
}
return 0;
}
inline ll Equ(ll a,ll b,ll p)
{
a%=p; b%=p;
abcd E=EXGCD(p,a);
ll d=p*E.first+a*E.second;
if (b%d==0)
return d;
else
return 0;
}
ll A,B,P;
ll ans,cnt;
struct data{
ll p,c,p_c;
};
data a[1000005];
int num;
inline void Machine(ll P)
{
num=0;
for (int i=2;P!=1 && i<=sqrt(P)+0.50;i++)
if (P%i==0)
{
a[++num].p=i;
a[num].p_c=1;
a[num].c=0;
while (P%i==0)
P/=i,a[num].c++,a[num].p_c*=i;
}
if (P!=1)
a[++num].p=P,a[num].c=1,a[num].p_c=P;
}
inline ll Cal(ll A,ll B,ll k)
{
ll phi=a[k].p_c-a[k].p_c/a[k].p;
ll g=GetRoot(a[k].p_c,phi);
ll ind=BSGS::Solve(g,B,a[k].p_c,phi);
ll ret=Equ(A,ind,phi);
return ret*Pow(a[k].p,cnt-cnt/A,1LL<<60);
}
int main()
{
ll Q,k,tmp;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(Q);
while (Q--)
{
read(A); read(B); read(k); P=2*k+1; B%=P;
Machine(P);
ans=1;
for (int i=1;i<=num;i++)
{
if (!ans) break;
if (B%a[i].p_c==0)
{
tmp=Pow(a[i].p,a[i].c-(a[i].c-1)/A-1,1LL<<60);
}
else
{
ll b=B;
cnt=0;
while (b%a[i].p==0)
{
cnt++; b/=a[i].p;
a[i].p_c/=a[i].p;
a[i].c--;
}
if (cnt%A)
tmp=0;
else
tmp=Cal(A,b,i);
}
ans*=tmp;
}
write(ans,'\n');
}
return 0;
}