你有一个质数 p p p和一个二元组 ( a , b ) (a,b) (a,b),它们的和不被 p p p整除。
你想对这个二元组进行若干次操作,让它们变成另外一个二元组。每一步,你可以对二元组做如下操作中的一个:
你需要回答 q q q次询问,每次询问,给你 ( a i , b i , c i , d i ) (a_i,b_i,c_i,d_i) (ai,bi,ci,di),问最少需要多少步才能将 ( a i , b i ) (a_i,b_i) (ai,bi)变成 ( c i , d i ) (c_i,d_i) (ci,di)。如果不可行,则输出 − 1 -1 −1。
p ≤ 1 0 9 + 7 , 1 ≤ q ≤ 1 0 5 , 0 ≤ a i , b i , c i , d i ≤ p − 1 , p ∤ ( a i + b i ) p\leq 10^9+7,1\leq q\leq 10^5,0\leq a_i,b_i,c_i,d_i\leq p-1,p\nmid (a_i+b_i) p≤109+7,1≤q≤105,0≤ai,bi,ci,di≤p−1,p∤(ai+bi)
设 t = a + b t=a+b t=a+b,我们发现在操作时 t m o d p t\bmod p tmodp是不变的。先判断 a + b a+b a+b和 c + d c+d c+d在 m o d p \bmod p modp的意义下是否相同,如果不同则无解。
如果相同,则 a = c , b = d a=c,b=d a=c,b=d等价于 a = c a=c a=c。一次操作中, a a a要么变成 2 a 2a 2a,要么变成 2 a − t 2a-t 2a−t。
所以 k k k次操作后, a a a就会变成 2 k a − q t 2^ka-qt 2ka−qt,其中 q q q可以为 [ 0 , 2 k ) [0,2^k) [0,2k)中的任意值。显然 2 k ≥ p 2^k\geq p 2k≥p时一定有解。
所以我们只需要枚举 k k k,判断 2 k a − c t \dfrac{2^ka-c}{t} t2ka−c在 m o d p \bmod p modp意义下是否 < 2 k <2^k <2k即可。
时间复杂度为 O ( q log p ) O(q\log p) O(qlogp)。
#include
using namespace std;
int ans;
long long p,q,a,b,c,d,t;
long long mi(long long t,long long v){
if(!v) return 1;
long long re=mi(t,v/2);
re=re*re%p;
if(v&1) re=re*t%p;
return re;
}
int main()
{
scanf("%lld%lld",&p,&q);
while(q--){
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
t=(a+b)%p;
if((a+b)%p!=(c+d)%p){
printf("-1\n");continue;
}
long long v=1,ny=mi(t,p-2);
for(ans=0;;v=v*2,ans++){
long long tmp=a*v;
if((tmp-c+p)%p*ny%p<v) break;
}
printf("%d\n",ans);
}
return 0;
}