题解 CF7C 【Line】

fls233666

2020-11-29 22:57:42

Solution

首先我们从这个直线方程入手: $$ Ax+By+C=0 $$ 也许我们并不能从这个普通的直线方程里面看出什么。 但如果移项一下: $$ Ax+By=-C $$ 好极了!现在这是**一个标准的二元一次不定方程**了! 下面我们考虑哪些数论知识和二元一次不定方程有关。 一般,我们会最先想到的两个定理,就是 [裴蜀定理](https://oi-wiki.org/math/bezouts/) 和 [扩展欧几里得定理](https://oi-wiki.org/math/gcd/) 。 为什么呢? 先简单说明一下这两个定理分布有什么用处。 - 裴蜀定理:用于判定一个一元二次不定方程是否有整数解。 - 扩展欧几里得定理:用于求出一个有整数解的一元二次不定方程 $ax+by=\gcd(a,b)$ 的一组可行解。 而再看题目要我们做的事情: - 判断直线上是否存在整点。 - 如果有整点,找到并输出一个整点。 正好和我们用这两个定理能做的事情一致! 下面开始介绍具体做法。 首先说明一下裴蜀定理的具体内容: **对于一个一元二次不定方程 $ax+by=c$ ,它有整数解,当且仅当 $c$ 能够被 $\gcd(a,b)$ 整除。** 由此,判断 $C$ 是否能被 $\gcd(A,B)$ 整除,即可得到是否有解。 有解之后,再使用扩展欧几里得定理,我们可以求得一组关于方程 $Ax+By=\gcd(A,B)$ 的可行解。记这组可行解为 $x_0,y_0$。因为我们真正要求解的方程是 $Ax+By=-C$ ,所以最终答案为 $x=x_0 \times \frac{-C}{\gcd(A,B)},y=y_0 \times \frac{-C}{\gcd(A,B)}$ 思路大致如上,下面就是代码: ```cpp #include<iostream> #include<cstdio> #define ll long long #define rgt register int using namespace std; ll a,b,c,x,y,g; ll exgcd(ll num1,ll num2){ //标准的EXgcd if(!num2){ x=1; y=0; //ax+by=a的一个可行解 return num1; //返回最大公约数 } ll tg=exgcd(num2,num1%num2); //辗转相除 ll tmp=x; x=y; y=tmp-y*(num1/num2); //转化可行解 return tg; //返回最大公约数 } int main(){ scanf("%lld%lld%lld",&a,&b,&c); g=exgcd(a,b); if(c%g) //由裴蜀定理判无解 printf("-1"); else{ //求出题目要的答案 x*=c/g; y*=c/g; printf("%lld %lld",-x,-y); } return 0; } ```