uva11768 - Lattice Point or Not 扩展gcd

解决如何计算带有浮点坐标的线段上整数点的数量问题,通过扩展欧几里得算法找到特定解,并利用最小公倍数确定整数点分布规律。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Now a days a very common problem is:“The coordinate of two points in Cartesian coordinate system is (200, 300) and(4000, 5000). If these two points are connected we get a line segment. How manylattice points are there on this line segment.” You will have to do a similartask in this problem – the only difference is that the terminal coordinates canbe fractions.

 

Input

First line of the input file contains a positive integer N(N<=50000) that denotes how many lines of inputs follow. This line isfollowed by N lines each of which contains four floating-point numbers x1, y1,x2, y2 (0< |x1|, |y1|, |x2|, |y2|<=200000). These floating-point numbers has exactly one digit after thedecimal point.

 

Output

For each line of input exceptthe first line produce one line of output. This line contains an integer whichdenotes how many lattice points are there on the line segment that connects thetwo points (x1, y1) and (x2, y2).

 

SampleInput                              Output for Sample Input

3

10.1 10.1 11.2 11.2

10.2 100.3 300.3 11.1

1.0 1.0 2.0 2.0

1

0

2


  这题好坑。。

  一开始就有想法,先找到离上面端点最近的一个在直线上的整点,然后根据最小公倍数的循环节算出这个点到下端点之间有多少个。

  小数乘以10,问题就变成了先找一个是10的倍数的点,把坐标带入得到方程(Y1-Y2)x+(X2-X1)y=Y1X2-Y2X1,把等号左边乘10变成10(Y1-Y2)x+10(X2-X1)y=Y1X2-Y2X1,用扩展gcd求出x,y,再乘以10,就成了10的倍数的解。这是个好方法~

      后面求循环节就类似于一个矩形对角线上能经过多少个整点的问题,答案是每经过gcd(N,M)有一个。还要注意的是根据解的位置分情况求出离上端点最近的整点,还有各种特判。。呵呵呵。。。

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<algorithm>
#define eps 1e-9
#define MAXN 30010
#define MAXM 110
#define MOD 999983
typedef long long LL;
using namespace std;
int T;
double t1,t2,t3,t4;
LL X1,Y1,X2,Y2;
void extend_gcd(LL a,LL b,LL& d,LL& x,LL &y){
    if(!b){
        d=a;
        x=1;
        y=0;
    }
    else{
        extend_gcd(b,a%b,d,y,x);
        y-=a/b*x;
    }
}
LL gcd(LL a,LL b){
    return a%b?gcd(b,a%b):b;
}
LL lcm(LL a,LL b){
    return a*b/gcd(a,b);
}
int get_one_reult(LL &x,LL &y){
    LL d;
    extend_gcd(10*(Y1-Y2),10*(X2-X1),d,x,y);
    if((Y1*X2-Y2*X1)%d!=0) return 0;
    x=10*x*(Y1*X2-Y2*X1)/d;
    y=10*y*(Y1*X2-Y2*X1)/d;
    return 1;
}
int main(){
    freopen("in.txt","r",stdin);
    scanf("%d",&T);
    while(T--){
        scanf("%lf%lf%lf%lf",&t1,&t2,&t3,&t4);
        if(t1>=0) X1=LL(t1*10+0.5);
        else X1=LL(t1*10-0.5);
        if(t2>=0) Y1=LL(t2*10+0.5);
        else Y1=LL(t2*10-0.5);
        if(t3>=0) X2=LL(t3*10+0.5);
        else X2=LL(t3*10-0.5);
        if(t4>=0) Y2=LL(t4*10+0.5);
        else Y2=LL(t4*10-0.5);
        if(Y1>Y2){
            swap(X1,X2);
            swap(Y1,Y2);
        }
        if(X1==X2&&Y1==Y2){
            if(X1%10||Y1%10) printf("0\n");
            else printf("1\n");
            continue;
        }
        LL N=abs(X1-X2),M=abs(Y1-Y2),x,y,ans,ymin,xmin;
        if(M==0){
            if(Y1%10){
                printf("0\n");
                continue;
            }
            if(X1>X2) swap(X1,X2);
            if(X1%10) xmin=X1+10-X1%10;
            else xmin=X1;
            if(xmin<=X2) ans=1+(X2-xmin)/10;
            else ans=0;
            printf("%lld\n",ans);
            continue;
        }
        if(N==0){
            if(X1%10){
                printf("0\n");
                continue;
            }
            if(Y1%10) ymin=Y1+10-Y1%10;
            else ymin=Y1;
            if(ymin<=Y2) ans=1+(Y2-ymin)/10;
            else ans=0;
            printf("%lld\n",ans);
            continue;
        }
        if(!get_one_reult(x,y)){
            printf("0\n");
            continue;
        }
        LL d=gcd(N,M);
        LL a=10/gcd(N/d,10),b=10/gcd(M/d,10),n=lcm(a,b),cirx=N/d*n,ciry=M/d*n;
        if(y>Y1) ymin=Y1+(y-Y1)%ciry;
        else{
            if((Y1-y)%ciry) ymin=Y1+ciry-(Y1-y)%ciry;
            else ymin=Y1;
        }
        xmin=(Y1*X2-Y2*X1+(X1-X2)*ymin)/(Y1-Y2);
        if(X1<=X2){
            if(xmin>=X1&&xmin<=X2) ans=1+(X2-xmin)/cirx;
            else ans=0;
        }
        else{
            if(xmin>=X2&&xmin<=X1) ans=1+(xmin-X2)/cirx;
            else ans=0;
        }
        printf("%lld\n",ans);
    }
    return 0;
}


### Flat-Lattice 的概念 Flat-lattice 是一种用于处理自然语言处理任务的数据结构,特别是在涉及词典信息的任务中表现出色。这种结构能够将复杂的 lattice 展平成更易于处理的形式,同时保留原有的语义关系[^2]。 在具体实现方面,flat-lattice 可以定义为一组跨度(span),其中每个跨度代表一个标记(即字符或单词),并附带头部和尾部索引,用来指示该标记在原序列中的起始和结束位置。对于单个字符而言,其头部和尾部索引相同;而对于多字符组成的词语,则会记录下整个词语范围内的首尾位置。 ### Flat-Lattice 的实现方式 为了更好地理解 flat-lattice 如何运作,下面给出一段 Python 代码作为示例: ```python class Span: def __init__(self, start, end, label): self.start = start self.end = end self.label = label def build_flat_lattice(tokens, dictionary): spans = [] # 构建基于字面意思的初始span列表 for i, token in enumerate(tokens): span = Span(i, i+1, 'char') spans.append(span) # 添加来自词典的新spans for entry in dictionary.entries(): positions = find_sublist_positions(tokens, entry.tokens()) for pos in positions: new_span = Span(pos, pos+len(entry), entry.name) spans.append(new_span) return sorted(spans, key=lambda s: (s.start, -s.end)) ``` 此函数 `build_flat_lattice` 接收两个参数:一个是待分析的文本分词结果 `tokens` ,另一个是从外部加载得到的领域特定术语库 `dictionary` 。通过遍历这些输入数据,程序创建了一系列 Span 对象,并按照它们在原文档中的顺序进行了排序。 ### 应用场景 FLAT 模型利用了上述提到的 flat-lattice 结构,在 Transformer 编码器之上引入了一种新的位置编码机制,使得模型能够在不改变内部架构的情况下融入额外的知识源——比如预先编译好的词汇表。这种方法不仅提高了实体识别任务的表现精度,同时也保证了高效的 GPU 并行运算能力[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值