zoukankan      html  css  js  c++  java
  • UVA 11768

    首先本题需要用到扩展欧几里得算法……


    关于exgcd算法的一点简略证明:



    那么,对于函数exgcd(a,b)=(d,x,y),其中d满足d=gcd(a,b); (x,y)满足ax+by=d;

    则exgcd(b,a mod b)=(d,x',y'),而此时,使用 x = y' ;  y = x' - floor(a/b) * y' = x' - floor(a/b) * x 就能得到exgcd(a,b)的值。

    故我们可以有扩展欧几里得算法如下:

    void exgcd(int a,int b,int &d,int &x,int &y){
        if(!b){d=a;x=1;y=0;}
        else {exgcd(b,a%b,d,y,x);y-=(a/b)*x;}
    }

    此处的边界条件是exgcd(a,0)=(a,1,0)


    那么此时,若c mod gcd(a,b) = 0,就容易求得一个整点(x,y),那么如何得到所有的点?



    然后是题目的代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 typedef long long ll;
     7 using namespace std;
     8 void exgcd(ll a,ll b,ll &d,ll &x,ll &y){  
     9     if(!b){d=a;x=1;y=0;}  
    10     else {exgcd(b,a%b,d,y,x);y-=(a/b)*x;}
    11 }
    12 int main() {
    13     double X1,Y1,X2,Y2;
    14     int t;
    15     scanf("%d",&t);
    16     while(t--){
    17         scanf("%lf%lf%lf%lf",&X1,&Y1,&X2,&Y2);//获得初始坐标(x1,y1),(x2,y2)
    18         ll x1=X1*10,x2=X2*10,y1=Y1*10,y2=Y2*10;//将坐标都换成整型
    19         if(x1==x2)//如果这条线是一条竖直的线
    20         {
    21             if(x1%10!=0){//如果此时的直线l:x=c,c不是整数,那么这条线上显然没有整点
    22                 printf("0
    ");
    23                 continue;
    24             }
    25             y2=floor(max(Y1,Y2));
    26             y1=ceil(min(Y1,Y2));
    27             printf("%lld
    ",y2-y1+1);
    28             continue;
    29         }
    30         if(y1==y2)//如果这条线是一条水平的线
    31         {
    32             if(y1%10!=0){//如果此时的直线l:y=c,c不是整数,那么这条线上显然也没有整点
    33                 printf("0
    ");
    34                 continue;
    35             }
    36             x2=floor(max(X1,X2));
    37             x1=ceil(min(X1,X2));
    38             printf("%lld
    ",x2-x1+1);
    39             continue;
    40         }
    41         ll a=(y2-y1)*10,b=(x1-x2)*10,c=x1*y2-x2*y1;//计算出l:ax+by=c
    42         ll x,y,d;
    43         if(X2<X1) swap(X2,X1);//确保x2>x1
    44         x1=ceil(X1),x2=floor(X2);
    45         if(x1>x2){//如果一条线的斜率过大,使得x1,x2有m<x1<x2<m+1 (m为整数),那么显然这个范围内没有整点
    46             printf("0
    ");
    47             continue;
    48         }
    49         ll k=0;
    50         exgcd(a,b,d,x,y);//得到满足ax+by=gcd(a,b)的(x0,y0)
    51         if (c%d==0)//如果c是gcd(a,b)的整数倍,即c = k * gcd(a,b),那么显然点( k * x0 , k * y0 )是ax+by=c上的一个整点
    52         {
    53             a/=d,b/=d;
    54             x*=c/d,y*=c/d;
    55             if(b<0) b=-b;
    56             x=x-(x-x1)/b*b;
    57             while(x<x1) x+=b;
    58             while(x+k*b<=x2) k++;
    59             printf("%lld
    ",k);
    60         }
    61         else printf("0
    ");
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    5.24Java对象流
    6.1Java多线程抢票龟兔赛跑
    5.29把分散的文件合并
    6.2Java静态代理设计模式
    5.31Java多线程继承
    5.31Java多线程开篇>java.thread
    6.1JavaStartThread
    命令行查看java classpath设置
    文本自动与不自动换行
    Tomcat 6 虚拟目录配置方法
  • 原文地址:https://www.cnblogs.com/dilthey/p/6804137.html
Copyright © 2011-2022 走看看