题目
LA 4270 Discrete Square Roots
题解
这题,,只做到一半然后就放弃了qwq明明再想一下就出来了。设原答案为r,可行解为R。则
r2=k1n+m
R2=k2n+m
有
r2?R2=(k1?k2)n
(r+R)(r?R)=(k1?k2)n
则一定存在a,b使得 a?b==n 且 (r+R)%a==0,(r?R)%b==0
于是
r+R=x?a,r?R=y?b
a?x+b?y=2r
先利用这个方程,枚举因数,解出一组解,因为有 r+R=x?a ,所以可以找出x所有合法的通解,计算出答案,扔到set里面。
代码
//QWsin
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;int x,n,r;void exgcd(ll a,ll b,ll &g,ll &x,ll &y)
{if(!b){g=a;x=1;y=0;return ;}exgcd(b,a%b,g,y,x);y-=a/b*x;
}set<ll>ans;
inline void work(ll a,ll b,ll c)
{ll g,x,y;exgcd(a,b,g,x,y);if(c%g) return ;x*=c/g;x=(x%(b/g)+b/g)%(b/g);//x转化为最小非负解ll s=a*x-c/2;//因为有r+R=ax,并且c=2r ll k=b/g*a;//因为x=x0+k*b' x每次加b',带回上面式子,ans每次加a*b'for(;s<n;s+=k) if(s>=0) ans.insert(s);
}int kase=0;
inline void solve()
{ans.clear();int sz=sqrt(n);for(int A=1;A<=sz;++A) if(n%A==0){work(A,n/A,r<<1);work(n/A,A,r<<1);} printf("Case %d:",++kase);for(set<ll>::iterator it=ans.begin();it!=ans.end();++it) printf(" %lld",*it);putchar('\n');
}int main()
{while(scanf("%d%d%d",&x,&n,&r)==3&&(x+n+r)) solve();return 0;
}