您的位置:首页 > 其它

sgu 106

2015-08-16 01:30 357 查看
给出a,b,c,x1,x2,y1,y2然后你要做的就是找出在矩形框内的整数点有多少个。

初始解(x*(-c)/g,y*(-c)/g)

然后对于x轴方向上的增量是 b/g

我写成几何了 我去 。。。好好的数论题。

先用扩展欧几里德求出初始解,获取到在离矩形框最近的点的x坐标。

然后计算直线和x=x1,x2,y=y1和y2上的点。

然后取中间两个。判断两个点是否都在矩形框上。如果存在一个就判断该点是不是整数点。

都不在就是0。都在就是 x1和x2距离的差值 求结果即可

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <utility>
#include <algorithm>
using namespace std;
typedef long long ll;
ll a,b,c,x1,x2,yy1,y2,flagx,flagy,ans;
const double eps=1e-20;
typedef  pair<double,double> P;
P p[5];
bool is()
{
    return x1>x2||yy1>y2?0:1;
}
bool isdouble(double x)///判断不是整数  ///加值的范围是多少
{
    return (fabs(x-(ll)(x+eps))>eps)?1:0;
}
ll exgcd(ll a,ll b,ll *x,ll *y)
{
    if(b==0)
    {
        *x=1;
        *y=0;
        return a;
    }
    ll xx,yy;
    ll g=exgcd(b,a%b,&xx,&yy);
    *x=yy;
    *y=xx-a/b*yy;
    return g;
}
double near(double x)
{
    return x>0?x+eps:x-eps;
}
int which(P &a,P &b)
{
    int answer1=0,answer2=0;
    if(!(a.first-x2>eps||x1-a.first>eps||a.second-y2>eps||yy1-a.second>eps)) answer1=1;
    if(!(b.first-x2>eps||x1-b.first>eps||b.second-y2>eps||yy1-b.second>eps)) answer2=2;
    return answer1+answer2;
}
double length(P &a,double x,double y)
{
    return (a.first-x)*(a.first-x)+(a.second-y)*(a.second-y);
}
int main()
{
    while(~scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&x1,&x2,&yy1,&y2))
    {
        if(!is())
        {
            printf("0\n");    ///对边界合法性的考虑
            continue;
        }
        ll maxx=max(x1,x2),minx=min(x1,x2);
        ll maxy=max(yy1,y2),miny=min(yy1,y2);
        if(a==0)///注意是整数点
        {
            if(b==0)
            {
                if(c==0) printf("%I64d\n",(abs(x1-x2)+1)*(abs(yy1-y2)+1));
                else printf("0\n");
                continue;
            }
            else
            {
                double ansy=-c*1.0/b;
                if(ansy<miny||ansy>maxy||isdouble(ansy)) printf("0\n");
                else printf("%I64d\n",abs(x1-x2)+1);
                continue;
            }
        }
        else
        {
            if(b==0)
            {
                double ansx=-c*1.0/a;
                if(ansx<minx||ansx>maxx||isdouble(ansx)) printf("0\n");///可能存在精度问题
                else printf("%I64d\n",abs(yy1-y2)+1);
                continue;
            }
            else
            {
                ans=0,flagx=1,flagy=1;
                if(a<0) flagx=-1;    ///扩展gcd求值为正值
                if(b<0) flagy=-1;
                ll x,y;
                ll g=exgcd(abs(a),abs(b),&x,&y);
                if((-c)%g!=0)
                {
                    printf("0\n");
                    continue;
                }
                x=x*(-c)/g*flagx;///增量为 k*b/g;
                y=y*(-c)/g*flagy;///增量为 -k*a/g;
                p[0].first=x1;
                p[0].second=(-c-a*x1)*1.0/b;
                p[1].first=x2;
                p[1].second=(-c-a*x2)*1.0/b;
                p[2].first=(-c-b*yy1)*1.0/a;
                p[2].second=yy1;
                p[3].first=(-c-b*y2)*1.0/a;
                p[3].second=y2;
                sort(p,p+4);
                int d=which(p[1],p[2]);
                if(d==0)
                {
                    printf("0\n");
                    continue;
                }
                if(d==1) if(!isdouble(p[1].first)&&!isdouble(p[1].second)) ans=1;///判断整数点
                if(d==2) if(!isdouble(p[2].first)&&!isdouble(p[2].second)) ans=1;
                if(d==3)
                {
                    if(p[1].first<=x&&x<=p[2].first)
                    {
                        ans=abs((ll)near(p[1].first)-x)/abs(b/g)+abs((ll)near(p[2].first)-x)/abs(b/g)+1;
                    }
                    else
                    {
                        ll ans1=abs((ll)near(p[1].first)-x)/abs(b/g);
                        ll ans2=abs((ll)near(p[2].first)-x)/abs(b/g);
                        ans=abs(ans1-ans2);
                        if(fabs(p[2].first-p[1].first)<eps&&fabs(p[2].second-p[1].second)<eps)
                        {
                            if(!isdouble(p[2].first)&&!isdouble(p[2].second)) ans+=1;
                        }
                        else
                        {
                            double len1=length(p[1],x,y),len2=length(p[2],x,y);
                            if(len1>len2) {if(!isdouble(p[2].first)&&!isdouble(p[2].second)) ans+=1;}
                            else if(!isdouble(p[1].first)&&!isdouble(p[1].second))   ans+=1;
                        }
                    }
                }
                printf("%I64d\n",ans);
            }
        }
    }
    return 0;
}


还可以直接算 思路也是找离矩形框的最近点。但是要同时判断x,y,可能出现x符合条件y不符合条件的情况。不用这么麻烦。。。。卧槽 我就是来卖萌的。。。。

顺便附上 啊mao题解http://www.cnblogs.com/hchlqlz-oj-mrj/p/4729996.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: