ACM.GCD与LCM

欧几里得算法
取模运算的运算规则
(a + b) % p = (a % p + b % p) % p
(a - b) % p = (a % p - b % p) % p
(a * b) % p = (a % p * b % p) % p
a ^ b % p = ((a % p)^b) % p
又名辗转相除法
代码实现过程
1非递归写法

int gcd(int a,int b)
{
int r=a%b;
while(r)
{a=b;
b=r;
r=a%b;
}
return b;
}

2递归写法

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

最小公倍数lcm(a,b)=ab/gcd(a,b)
最大公约数和最小公倍数的一些性质
gcd(a , b) = gcd(b , a-b)
gcd(ma , mb) = m
gcd(a , b), m为一个自然数
gcd(a+mb , b) = gcd(a , b)
m=gcd(a , b) 则gcd(a/m,b/m)=gcd(a,b)/m
gcd(a, lcm(b, c)) = lcm(gcd(a, b), gcd(a, c))
lcm(a, gcd(b, c)) = gcd(lcm(a, b), lcm(a, c))

一.NEFU-992
又见GCD
Problem:B
Time Limit:1000ms
Memory Limit:65536K
Description
有三个正整数a,b,c(0<a,b,c<10^6),其中c不等于b。若a和c的最大公约数为b,现已知a和b,求满足条件的最小的c。
Input
每行输入两个正整数a,b。
Output
输出对应的c,每组测试数据占一行
Sample Input
6 2
12 4
Sample Output
4
8
i每次递增的值设为b即可

#include <bits/stdc++.h>
using namespace std;
int i;
int main()
{
    int a,b,c,g;
    while(cin>>a>>b)
    {
        int min=999999;
      for(i=b*2;;i+=b)
      {
          if(__gcd(i,a)==b){min=i;
          break;
      }}
      cout<<min<<endl;
    }
    return 0;
}

二.NEFU-764
多个数的最大公约数
Problem:C
Time Limit:1000ms
Memory Limit:65536K
Description
给定n(n<=10)个正整数,你的任务就是求它们的最大公约数,所有数据的范围均在long long内。
Input
输入数据有多组,每组2行,第一行为n,表示要输入数字的个数,接下来第二行有n个正整数。
Output
输出一个数,即这n个数的最大公约数。
Sample Input
5
2 4 6 8 10
2
13 26
Sample Output
2
13依次求每两个数的最大公因数即可,类似于斐波那契数列

#include <bits/stdc++.h>
using namespace std;
int main()
{
    long long n;
    while(cin>>n)
    {
        long long ans=1,i;
        long long a[n];
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
        }
         for(i=1;i<=n-1;i++)
         {
             a[i+1]=__gcd(a[i],a[i+1]);
         }
        cout<<a[n-1]<<endl;
    }
    return 0;
}

三.NEFU-765
多个数的最小公倍数
Problem:D
Time Limit:1000ms
Memory Limit:65536K
Description
给定n(n<=10)个正整数,你的任务就是求它们的最小公倍数,所有数据的范围均在long long内。
Input
输入数据有多组,每组2行,第一行为n,表示要输入数字的个数,接下来第二行有n个正整数。
Output
输出一个数,即这n个数的最小公倍数。
Sample Input
5
2 4 6 8 10
2
13 26
Sample Output
120
26
原理同上一道题

#include <bits/stdc++.h>
using namespace std;
int i;
int main()
{
    long long n;
    while(cin>>n)
    {
        long long ans=1;
        long long a[n];
        for(i=0;i<n;i++)
        {
            cin>>a[i];
            ans=(ans*a[i]/__gcd(ans,a[i]));
        }

        cout<<ans<<endl;
    }
    return 0;
}

五.NEFU-1669
高木同学的因子
Problem:G
Time Limit:1000ms
Memory Limit:65535K
Description
今天西片同学又被高木同学捉弄了,高木同学跟西片同学玩了这么一个游戏。两人心中分别想一个数字,这两个数字分别为x和y(1<=x,y<=1e18),然后让西片同学说出一共有多少个整数既是x的因子,又是y的因子。由于西片和高木很有默契,所以保证他们两个想的数x和y的最大公因数不会超过1e9。这个问题又难住了西片同学了,你能帮帮西片同学告诉他答案吗?
Input
单组输入
数据占一行,包含两个整数x和y(1<=x,y<=1e18),保证gcd(x,y)<=1e9。
Output
输出既是x因子又是y因子的整数的个数。输出占一行
Sample Input
12 36
Sample Output
6

因为x和y都是很大的数字,直接暴力计算不可取,两个数的公因子中的最大值应为最大公因数,其他因子都为最大公因子的因子,因此将问题转化为求最大公因子的因子个数。

#include <bits/stdc++.h>
using namespace std;
long long gcd(long long x , long long y)
{
    if(y == 0) return x;
    else return gcd(y , x % y);
}
int main()
{
       long long m,n,i;
       cin>>m>>n;
       int daan=0;
       long long q=gcd(m,n);
       for(i=1;i*i<q;i++)            //只判断一半
       {
           if(q%i==0)daan+=2;      //此处每次加上2,因为循环条件判断的是一半,每次加一对数
       }
       if(i*i==q)daan++;
       cout<<daan<<endl;
       return 0;
}
发布了5 篇原创文章 · 获赞 0 · 访问量 47

猜你喜欢

转载自blog.csdn.net/abysswatcher1/article/details/103911326