zoukankan      html  css  js  c++  java
  • LightOJ

    题目大意:给你一个方程ax+by+c=0(x1<=x<=x2&&y1<=y<=y2)

    求其整数解个数

    具体思路:扩展欧几里得求一个特解,然后求一下x和y的最少变化量,

    然后求出当x1<=x<=x2,与其对应的y的范围,和y1<=y<=y2做一个并,在算一下有几个解就好了

    花絮:一开始我发现x=x0+xx*t(x0为特解,xx为最少变化量)y=y0-yy*t,并试图求出t的范围,wa了几发之后发现有许多+1-1的奇怪地方需要处理,于是果断换了一个做法

            结果却还是wa,通过一些特殊手段发现好像是我为了把方程变为ax+by=c,我把读入的c取反,但前面的特判写的比较早~~~

    扩展欧几里得是什么勒?

    欧几里得算法可以求最大公约数

    int gcd(int a,int b){if(b==0)return a;else return gcd(b,a%b);}

    然后扩展欧几里得可以求ax+by=gcd(a,b)的一组解

    怎么求的呢?

    因为gcd(a,b)=gcd(b,a%b)

    所以ax+by=gcd(a,b)可以变为

    b*x1+(a%b)*y1=gcd(b,a%b)=ax+by

    然后一顿公式变形

    b*x1+(a%b)*y1=b*x1+(a-[a/b]*b)*y1([]为下取整)

    =b*x1+(a-[a/b]*b)*y1=a*y1+b*(x1-[a/b]*y1)=ax+by

    所以x=y1  y=x1-[a/b]*y1

    于是可以写成这样

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

    最后是AC代码

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define int long long 
    using namespace std;
    int T;
    int gcd(int a,int b){if(b==0)return a;else return gcd(b,a%b);}
    void exgcd(int a,int b,int& d,int& x,int & y)
    {
        if(b==0)d=a,x=1,y=0;
        else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
    }
    main()
    {
        scanf("%lld",&T);
        int t;
        for (t=1;t<=T;t++)
        {
            
            int a,b,c,X1,X2,Y1,Y2;
            scanf("%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&X1,&X2,&Y1,&Y2);c=-c;
            printf("Case %lld: ",t);
            if(a==0&&b==0)
            {
                if(c==0) printf("%lld
    ",(Y2-Y1+1)*(X2-X1+1));else puts("0");
                continue;  
            }
            else if(a==0)
            {
                if(c%b!=0) puts("0");
                else
                {
                    int z=c/b;
                    if(z>=Y1&&z<=Y2) printf("%lld
    ",(X2-X1+1));else puts("0");
                }
                continue;
            }
            else if(b==0)
            {
                int z=c/a;
                if(c%a!=0) puts("0");
                else if(z>=X1&&z<=X2) printf("%lld
    ",(Y2-Y1+1));
                else puts("0");
                continue;
            }
            int g=gcd(a,b);
            if(c%g)
            {
                puts("0");
                continue;
            }
            int x,y;
            exgcd(a,b,g,x,y);
            x=x*(c/g),y=y*(c/g);
            int xx=b/g,yy=a/g,Ymn,Ymx;
            X1=((x-X1)%xx+abs(xx))%abs(xx)+X1;
            X2=((x-X2)%xx-abs(xx))%abs(xx)+X2;
            if(X1>X2){printf("0
    ");continue;}
            
            Ymn=(-yy)*((X1-x)/xx)+y;
            Ymx=(-yy)*((X2-x)/xx)+y;
            if(Ymn>Ymx)swap(Ymn,Ymx);
            Y1=max(Y1,Ymn);
            Y2=min(Y2,Ymx);
            Y1=((y-Y1)%yy+abs(yy))%abs(yy)+Y1;
            Y2=((y-Y2)%yy-abs(yy))%abs(yy)+Y2;
            if(Y1>Y2)puts("0");else printf("%lld
    ",(Y2-Y1)/abs(yy)+1);
        }
        return 0;
    }
    
    
  • 相关阅读:
    CF-807B
    CF-807A
    sort()的升降序函数操作
    CF-805D
    CF-805B
    CF-805A
    CF-796C
    CF-796B
    图论学习四之Disjoint set union并查集
    图论学习三之Shortest Path最短路
  • 原文地址:https://www.cnblogs.com/Orange-User/p/7757966.html
Copyright © 2011-2022 走看看