您的位置:首页 > 其它

uva1426 - Discrete Square Roots 模线性方程

2014-07-03 14:28 288 查看
A square root of a number x is a number
r such that r2 = x. A discrete square root of a non-negative integerx is a non-negative integer
r such that r2


x mod
N , 0

r <N , where
N is a specific positive integer and mod is the modulo operation.

It is well-known that any positive real number has exactly two square roots, but a non-negative integer may have more than two discrete square roots. For example, forN = 12 , 1 has four discrete square roots 1, 5, 7 and
11.

Your task is to find all discrete square roots of a given non-negative integerx. To make it easier, a known square root
r of x is also given to you.

Input

The input consists of multiple test cases. Each test case contains exactly one line, which gives three integersx,
N and r.
(1

x <N, 2

N
< 1, 000, 000, 000, 1

r <
N). It is guaranteed that r is a discrete square root ofx modulo
N. The last test case is followed by a line containing three zeros.

Output

For each test case, print a line containing the test case number (beginning with 1) followed by a list of corresponding discrete square roots, in which all numbers are sorted increasingly..

Sample Input

1 12 1
4 15 2
0 0 0

Sample Output

Case 1: 1 5 7 11
Case 2: 2 7 8 13

给你一个满足0<=r<n且r^2=x(mod n)的r1,找出所有满足这个条件的的r。

设另一个解为r2。

r1^2+k1*n=x

r2^2+k2*n=x

因此r1^2-r2^2=(r1+r2)(r1-r2)=k3*n

设A*B=n

K1*A=r1+r2

K2*B=r1-r2

因此A*K1=2*r1 mod B

用模线性方程找出k1之后r2=ak1-r1,判断是否满足条件。

注意和一般的模线性方程有点不一样,因为最后是模n下的,不是模B下的,所以不只d个解,要找全N之内的所有解。

线性模方程的做法:在模n下,先用扩展gcd找到ax=b mod n的一个解x0,设e=x0+n,方程ax=b(mod n)的最小整数解x1=e mod(n/d),最大整数解x2=x1+(d-1)*(n/d)。

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<algorithm>
#define eps 1e-9
#define MAXN 510
#define MAXM 110
#define MOD 100000007
typedef long long LL;
using namespace std;
LL X,N,R;
set<LL> s;
void extend_gcd(LL a,LL b,LL& d,LL& x,LL& y){
if(!b){
d=a;
x=1;
y=0;
}
else{
extend_gcd(b,a%b,d,y,x);
y-=a/b*x;
}
}
void mod_line_equation(LL a,LL b,LL n){
LL x,y,d;
extend_gcd(a,n,d,x,y);
if(b%d==0){
x=(x*b/d%(n/d)+n/d)%(n/d);
LL t=a*x-R,cir=a*n/d,ans=t;
while(ans<N){
if(ans>=0&&ans*ans%N==X%N) s.insert(ans);
ans+=cir;
}
}
}
int main(){
freopen("in.txt","r",stdin);
int cas=0;
while(scanf("%lld%lld%lld",&X,&N,&R)&&(X||N||R)){
s.clear();
LL sq=sqrt(N)+0.5;
for(LL i=1;i<=sq;i++) if(N%i==0){
mod_line_equation(i,2*R,N/i);
mod_line_equation(N/i,2*R,i);
}
printf("Case %d:",++cas);
set<LL>::iterator it;
for(it=s.begin();it!=s.end();it++) printf(" %lld",*it);
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: