gcd

Description
Ivan is going to sleep now and wants to set his alarm clock. There will be many necessary events tomorrow, the i-th of them will start during the xi-th minute. Ivan doesn’t want to skip any of the events, so he has to set his alarm clock in such a way that it rings during minutes x1,x2,…,xn, so he will be awake during each of these minutes (note that it does not matter if his alarm clock will ring during any other minute).

Ivan can choose two properties for the alarm clock — the first minute it will ring (let’s denote it as y) and the interval between two consecutive signals (let’s denote it by p). After the clock is set, it will ring during minutes y,y+p,y+2p,y+3p and so on.

Ivan can choose any minute as the first one, but he cannot choose any arbitrary value of p. He has to pick it among the given values p1,p2,…,pm (his phone does not support any other options for this setting).

So Ivan has to choose the first minute y when the alarm clock should start ringing and the interval between two consecutive signals pj in such a way that it will ring during all given minutes x1,x2,…,xn (and it does not matter if his alarm clock will ring in any other minutes).

Your task is to tell the first minute y and the index j such that if Ivan sets his alarm clock with properties y and pj it will ring during all given minutes x1,x2,…,xn or say that it is impossible to choose such values of the given properties. If there are multiple answers, you can print any.

Input
The first line of the input contains two integers n and m (2≤n≤3⋅105,1≤m≤3⋅105) — the number of events and the number of possible settings for the interval between signals.

The second line of the input contains n integers x1,x2,…,xn (1≤xi≤1018), where xi is the minute when i-th event starts. It is guaranteed that all xi are given in increasing order (i. e. the condition x1<x2<⋯<xn holds).

The third line of the input contains m integers p1,p2,…,pm (1≤pj≤1018), where pj is the j-th option for the interval between two consecutive signals.

Output
If it’s impossible to choose such values y and j so all constraints are satisfied, print “NO” in the first line.

Otherwise print “YES” in the first line. Then print two integers y (1≤y≤1018) and j (1≤j≤m) in the second line, where y is the first minute Ivan’s alarm clock should start ringing and j is the index of the option for the interval between two consecutive signals (options are numbered from 1 to m in the order they are given input). These values should be chosen in such a way that the alarm clock will ring during all given minutes x1,x2,…,xn. If there are multiple answers, you can print any.

Examples
input
3 5
3 12 18
2 6 5 3 3
output
YES
3 4
input
4 2
1 5 17 19
4 5
output
NO
input
4 2
1 5 17 19
2 1
output
YES
1 1

题意:给你n件事开始的时间,m个可选的闹钟响的时间间隔,要你选闹钟第一次响的时间,和时间间隔,使得每件事开始的那一刻闹钟会响。

做法: y,y+p,y+2p,y+3p ……首先,闹钟第一次响应选择第一件事开始的时间,然后把之后的每件事开始的时间减去第一件事开始的时间,得到n1p,n2p,n3p,……设这个序列为x,则我们应选择一个时间间隔,是序列x的所有数的因子。我们可以先把序列x的gcd求出来,设为num,然后去看看在可选的时间间隔中有没有某一个数是num的因子,有就为答案,没有就是NO。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 300005;
ll a[maxn],b[maxn],x[maxn];

ll gcd(ll a,ll b)
{
    return a%b?gcd(b,a%b):b;
}

int main()
{
    ll n,m;
    cin>>n>>m;
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
    }
    for(int i=1; i<=m; i++)
    {
        cin>>b[i];
    }
    for(int i=1; i<n; i++)
    {
        x[i] = a[i+1] - a[1];
    }
    int flag = 0;
    ll ans;
    if(n>=3)
    {
        ll num = gcd(x[1],x[2]);
        for(int i=3; i<n; i++)
        {
            num = gcd(num,x[i]);
        }
        for(int i=1; i<=m; i++)
        {
            if(num%b[i]==0)
            {
                ans = i;
                flag = 1;
                break;
            }
        }
    }
    else
    {
        for(int i=1; i<=m; i++)
        {
            if(x[1]%b[i]==0)
            {
                flag = 1;
                ans = i;
                break;
            }
        }
    }
    if(flag)
    {
        printf("YES\n");
        cout<<a[1]<<" "<<ans;
    }
    else
    {
        printf("NO");
    }
}

Description
Neko loves divisors. During the latest number theory lesson, he got an interesting exercise from his math teacher.

Neko has two integers a and b. His goal is to find a non-negative integer k such that the least common multiple of a+k and b+k is the smallest possible. If there are multiple optimal integers k, he needs to choose the smallest one.

Given his mathematical talent, Neko had no trouble getting Wrong Answer on this problem. Can you help him solve it?

Input
The only line contains two integers a and b (1≤a,b≤109).

Output
Print the smallest non-negative integer k (k≥0) such that the lowest common multiple of a+k and b+k is the smallest possible.

If there are many possible integers k giving the same value of the least common multiple, print the smallest one.

Examples
input
6 10
output
2
input
21 31
output
9
input
5 10
output
0
Note
In the first test, one should choose k=2, as the least common multiple of 6+2 and 10+2 is 24, which is the smallest least common multiple possible.

题意:给你两个数a,b,要你找一个k值,使得a+k,b+k的最小公倍数最小,如果有多个一样的最小公倍数,输出最小的k值。

做法:平时都用辗转相除法求gcd,其实求gcd还有一个叫更相减损术的东东,即gcd(a,b) = gcd(a,b-a) (a<b)。所以gcd(a+k,b+k) = gcd(a+k,b-a),即a+k,b+k的最大公因数一定是b-a的因数,那么我们可以枚举b-a的因数,然后求出k,再去求lcm,找出答案。怎么得到k呢?设i是其中一个因子,a1 = a/i * i,k = a1 - a。
(一开始没开ll,wa了一次,后来是没判两个数相等的情况,再后来是ll下的INF设错了。。。噢 还有一开始连样例都没过是ceil用错了)

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 505;

ll gcd(ll a,ll b)
{
    return a%b?gcd(b,a%b):b;
}

int main()
{
    ll a,b;
    cin>>a>>b;
    ll num = abs(b-a),ans = INF,tmp,lcm = INF;//tmp存当前的lcm,ans存答案
    for(ll i=1; i<=sqrt(num); i++)
    {
        if(num%i == 0)
        {
            ll a1 = ceil((double)a/i)*i;
            ll k = a1 - a;
            tmp = (a+k)*(b+k)/gcd(a+k,b+k);
            if(tmp < lcm || (tmp == lcm && k < ans))
            {
                lcm = tmp;
                ans = k;
            }

            if(i != (num / i))
            {
                a1 = ceil((double)a/(num/i))*(num/i);
                k = a1 - a;
                tmp = (a+k)*(b+k)/gcd(a+k,b+k);
                if(tmp < lcm || (tmp == lcm && k < ans))
                {
                    lcm = tmp;
                    ans = k;
                }
            }
        }
    }
    if(ans != INF)
    cout<<ans;
    else
    cout<<"0";
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值