YACS 2023年8月月赛 甲组 T2 直线整点 题解

发布时间 2023-08-27 12:03:48作者: Xy_top

简单题,先二分出直线上 $x$ 最小的点使得这个点在矩形内。

然后不断跳,直到遇到整点。(实际上要用扩欧,但初测能过于是就偷个懒没写) 

接着不断跳直到不符合条件。

先 $\sqrt{V}$ 个跳一下,跳完后再一个一个跳就不用写二分了多好。

代码:

#include<iostream>
#define int long long
using namespace std;
double a,b,c,k;
double x1,x2,y1,y2;
int gcd(int a,int b){
    if(b==0)return a;
    return gcd(b,a%b);
}
double check(int mid){return (-a*mid-c)/b;}
//-a*x%b==c
signed main(){
    cin>>a>>b>>c>>x1>>x2>>y1>>y2;
    //b/gcd(a,b);
    int l=x1,r=x2,mid;
    if((a>0)^(b>0))k=1;
    else k=-1;
    while(l<=r){
        mid=l+r>>1;
        double y=check(mid);
        if(y<y1){
            if(k==-1)r=mid-1;
            else l=mid+1;
        }else if(y>y2){
            if(k==-1)l=mid+1;
            else r=mid-1;
        }else r=mid-1;
    }
    double y=-a/b*(r+1)-c/b;
    if(y<y1||y>y2){
        cout<<0;
        return 0;
    }
    int ans=r+1,sum=0,d=(int)(b)/gcd(a,b);
     while((int)(-a*ans-c)%(int)b!=0)++ans;
    if(ans<x1)ans+=d;
    if(ans>x2){
        cout<<0;
        return 0;
    }
    sum=1;
    int t=(int)(b)/gcd(a,b);

    if(t<0)t=-t;
    while(ans+31622*t<=x2&&ans+31622*t>=x1&&check(ans+31622*t)>=y1&&check(ans+31622*t)<=y2){
        ans+=31622*t;
        sum+=31622;
    }
    while(ans+t<=x2&&ans+t>=x1&&check(ans+t)>=y1&&check(ans+t)<=y2){
        ans+=t;
        ++sum;
    }
    cout<<sum;
    return 0;
}