UVA1426 Discrete Square Roots

思路:(exgcd)

提交:(2)

错因:输出格式错误OTZ

题解:

求:(r^2 ≡ x mod N , 0 leq r < N),并且题目会给出 (x,N) 和一个合法的(r_0)
原式可以转化为 (r^2-r_0^2equiv 0 mod N)
((r+r_0)*(r-r_0) equiv 0 mod N)
可以得到 ((r + r_0)*(r - r_0) = k * n)
假设 (n = a * b)
那么 可以知道
((r + r_0) \% a == 0 && (r - r_0) \% b == 0 ||\ (r + r_0) \% b == 0 && (r - r_0) \% a == 0,)
也就是
(r + r_0 = k1 * a)
(r - r_0 = k2 * b)
(k1 * a + k2 * b = 2 * r_0)
于是枚举约数,(exgcd),然后答案扔到(set)里正好排序(+)去重。

代码:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<set>
#define ll long long
#define rr register ll
#define R register int
using namespace std;
namespace Luitaryi {
template<class I> inline I g(I& x) { x=0; register I f=1;
  register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
  do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
} 
inline ll exgcd(int a,int b,ll& x,ll& y) {
  if(!b) {x=1,y=0; return a;}
  rr d=exgcd(b,a%b,y,x); y-=a/b*x; return d;
} int T; ll n,m,r0;
set<ll> s;
inline void solve(int a,int b,int c) {
  rr x,y; rr d=exgcd(a,b,x,y); if(c%d) return ;
  rr tmp,der=abs(b/d); x*=c/d; x=(x%der+der)%der; y=x; while(1) {
    tmp=a*x-r0; if(tmp>=0) {
      if(tmp>=n) break; s.insert(tmp);
    } x+=der;
  } x=y; while(1) {
    tmp=a*x-r0; if(tmp<=n) {
      if(tmp<0) break; s.insert(tmp);
    } x-=der;
  } 
}
inline void main() {
  while(g(m),g(n),g(r0),m||n||r0) {
    s.clear(); s.insert(r0);
    for(R i=1;i<=sqrt(n);++i) {
      if(n%i==0) solve(i,n/i,2*r0),solve(n/i,i,2*r0);
    } printf("Case %d:",++T); 
    for(set<ll>::iterator it=s.begin();it!=s.end();++it) printf(" %lld",*it); puts("");
  }
}
} signed main() {Luitaryi::main(); return 0;}

2019.08.23
77

原文地址:https://www.cnblogs.com/Jackpei/p/11402062.html