Daimayuan Online Judge 跳跳

代码源每日一题

平面上给定了一些整点(横纵坐标均为整数的点),被称为 “魔法阵”。魔法少女派派想要在各魔法阵之间传送,每一次传送,她将使用下面的方式:

  1. 刚开始,派派已经位于某传送阵之上;
  2. 如果派派掌握一种魔法 (A,B)(A,B),其中 A,BA,B 均为整数。使用一次这个魔法可以让派派从任意整点 (X,Y)(X,Y) 瞬间移动至 (X+A,Y+B)(X+A,Y+B);
  3. 选择一种魔法并开始传送,在一次传送过程中可以使用多次该魔法,但在抵达下一个传送阵之前仅能使用这一种魔法

问派派至少需要掌握多少种魔法,才能在从任意魔法阵直接传送到任意魔法阵?

输入格式

第一行一个整数 NN。

接下来一行 NN 行,每行包含两个整数 Xi,YiXi,Yi, 表示每个魔法阵的坐标。

输出格式

一个数,表示答案。

样例1输入

3
1 1
4 5
1 4

样例1输出

6

解释: 任务是从 (1,1)(1,1) 传送至 (4,5)(4,5) 以及 (1,4)(1,4) 、从 (4,5)(4,5) 传送至 (1,1)(1,1) 以及 (1,4)(1,4) 、从 (1,4)(1,4) 传送至 (1,1)(1,1) 以及 (4,5)(4,5) 。

注意你不能使用 (0,3)+(3,1)(0,3)+(3,1) 的魔法从 (1,1)(1,1) 到达 (4,5)(4,5)。因为每次移动,你只能使用一种魔法。

当然,你可以学习 (0,1)(0,1),那样的话,从 (1,1)(1,1) 到达 (1,4)(1,4) 则需要使用 33 次 (0,1)(0,1) 魔法了。

样例2输入

3
1 1
2 2
1000000000 1000000000

样例2输出

2

数据规模

  • N∈[10,500]N∈[10,500]
  • Xi,Yi∈[0,109]Xi,Yi∈[0,109], 但保证坐标之间两两不同

思路:题目让我们求迈的步数种类最少,我们一步跨多大都可以,假设我们现在直接一步迈到指定位置,当点数是倍数时它们可以用相同的步伐大小来到达,所以每一步走的越小越好,我们可以得到两点之间的x,y的差值,因为每一步走的都是相同的,我们改变一步的大小是不会影响能否到达的,那么我们就走最小的距离,假设一步能到达的距离是(2,4),那么我们一步走成(1,2)也是能够到的,我们求出x,y的gcd,然后再除去gcd就能让每一步都最小(x与y是对应的,不用担心(1,3)这类的距离大小)。只要将重复的步伐大小去掉即可。注意x=0,y=0时的情况,就让不为0 的数走成1即可。最后注意一下正负即可,别求出负的gcd,一除成了正数。

map的赋值方法:直接将map的第一个数变成下标,将第二个数赋值给map带下标即可。

pair:有pair时用 {} 大括号包住两个数即可。访问时需要用到 .first 与 .second,引用即可。

完整代码:

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pii;
typedef long long ll;
typedef vector<int> vi;
//#define int long long
#define fir first
#define sec second
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)x.size()
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define repd(i, l, r) for (int i = l; i >= r; --i)
#define pb push_back


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n;
    cin>>n;
    vector<pii>v;
    map<pii,int>mp;
    int l,r;
    rep(i,1,n)
    {

        cin>>l>>r;
        v.pb({l,r});
    }

    int ans=0;
    rep(i,0,n-1)
    {
        rep(j,0,n-1)
        {
            if(i==j)continue;
            int x=v[i].fir-v[j].fir;
            int y=v[i].sec-v[j].sec;

            if(x==0||y==0)
            {
                x= x!=0 ? x/abs(x):0;
                y= y!=0 ? y/abs(y):0;
            }
            else
            {
                int num = abs(__gcd(x, y));
				x /= num;
				y /= num;
            }
            if(mp[{x,y}]==0)
            {
                ans++;
                mp[{x,y}]=1;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值