UVA1426 Discrete Square Roots

思路:\(exgcd\)

提交:\(2\)

错因:输出格式错误OTZ

题解:

求:\(r^2 ≡ x \mod N , 0 \leq r < N\),并且题目会给出 \(x,N\) 和一个合法的\(r_0\)
原式可以转化为 \(r^2-r_0^2\equiv 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

posted @ 2019-08-23 19:00  LuitaryiJack  阅读(104)  评论(0编辑  收藏  举报