林大OJ (24.4)

目录

1.gcd和lcm

2.又见gcd

3.n个数gcd

4.n个数的lcm

5.x(gcd)y(lcm)之间的数

6.已知和&lcm

7.两数共同因子个数

8.取幂求余

9.库特的数学题

10.异或方程解的个数


1.gcd和lcm

Description
请计算2个数的最大公约数和最小公倍数;(最大公约数可以使用辗转相除法,最小公倍数=2个数的乘积/它们的最大公约数;)
Input
输入数据有多组,每组2个正整数a,b(2<a,b<1000)
Output
在一行内输出a和b的最大公约数和最小公倍数;
Sample Input
15 10
Sample Output
5 30
分析:思路很简单,这次先用非递归写gcd,下次可以试试递归

#include <bits/stdc++.h>
using namespace std;

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

main()
{
    int m,n;
    cin>>m>>n;
    int x,y;
    x=gcd(m,n);
    y=m/x*n;
    cout<<x<<" "<<y;
}

2.又见gcd

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

分析:由于ac的最大公约数是b,所以a%b=0,c%b=0,即a=k*b,c=k1*b

#include <bits/stdc++.h>

using namespace std;

main()
{
    int a,b;
    int i;
    while(cin>>a>>b)
    {
           for(i=2;;i++)
    {
        if(b*i!=a)
        {
            cout<<b*i<<endl;
            break;
        }
    }
    }

}

3.n个数gcd

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
 

分析:思路很简单,从第一个开始逐个求gcd即可

#include <bits/stdc++.h>

using namespace std;

main()
{
    int n,i,x,y;
    while(cin>>n)
    {
        cin>>x;
        for(i=1;i<n;i++)
        {
            cin>>y;
            x=__gcd(x,y);
        }
        cout<<x<<endl;
    }
}

4.n个数的lcm

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

分析:逐个求lcm,在求lcm时符号有一些绕,要注意

#include <bits/stdc++.h>

using namespace std;
main()
{
    int n,i,x,y,ans;
    while(cin>>n)
    {
        cin>>ans;
        for(i=1;i<n;i++)
        {
            cin>>y;
            x=__gcd(ans,y);
            ans=ans/x*y;
        }
        cout<<ans<<endl;

    }
}

5.x(gcd)y(lcm)之间的数

Description
jwGG最近沉迷于数论,他最近在研究最小公倍数和最大公约数,他的队友yzMM正好对数论也有些研究,于是yzMM给jwGG出了一个简单的数论题:在[x,y]区间中,求两个整数最大公约数是x且最小公倍数是y的个数。

yzMM善意地提醒,x和y可能到1e12那么大,jwGG这下可犯了难,这到底该怎么做呢?聪明的你能帮帮他吗?
Input
第一行输入一个T(T<=100),表示有T组数据,接下来每组输入两个数x,y(1<=x<=y<=1e12)(含义如题)
Output
输出一行表示答案。
Sample Input
1
2 12
Sample Output
4

分析:x为最大公约数,所以能得到的数一定的x的倍数,所以只用从x的倍数里求就好,但是要注意,x的倍数的最大公约数不一定时x。但是在做的时候我本来是打算让j从i开始,这样会减少循环次数,但是输出一直为2,到后来看了输出是(2,12) (4,6) (6,4) (12,2)才发现可以反过来,本来想到的是直接count*2,但是又想到了【x,x²】的特例,由于y只可能会是一个x的平方,所以判断一下如果count是奇数,就*2-1输出,如果是偶数就直接*2

#include <bits/stdc++.h>

using namespace std;

main()
{
    long long int x,y,a,b,t;
    int i,j;
    int count;
    int n;
    cin>>n;
    while(n--)
    {
        count=0;
        cin>>x>>y;
        for(i=1;; i++)
        {
            for(j=i;; j++)
            {
                a=x*i;
                b=x*j;
                if(b>y) break;
                t=__gcd(a,b);
                if(a/t*b==y && t==x ) count++;
            }
            if(i*x>y) break;
        }
        if(count%2==0) cout<<count*2<<endl;
        else cout<<count*2-1<<endl;
    }
}

6.已知和&lcm

Description
x+y=a,lcm(x,y)=b;已知a和b求解x^2+y^2
Input
多组数据输入。
第一行一个t表示a,b数对的数量。
接下来t行2个数表示a,b
T<=100000
a,b<10^9;
Output
每组样例输出t行每行一个数表示x^2+y^2;
Sample Input
2
6 4
6 3
Sample Output
20
18
分析:让x小于a,y等于a-x,再计算它们的最小公倍数,满足条件即可

          由于x和y可以是交换顺序的,但是结果不变,所以可以提前停止,可以用break,以可以从for中减少循环次数,但是要注意/2+1,或者是<=a/2

#include <bits/stdc++.h>

using namespace std;

main()
{
    int x,y,a,b,i,j;
    int n,t;
    cin>>n;
    while(n--)
    {
        cin>>a>>b;
        for(i=1;i<a/2+1;i++)
        {
            x=i;
            y=a-i;
            t=__gcd(x,y);
            if(x/t*y==b) 
            {
                cout<<x*x+y*y<<endl;
                break;
            }
        }
    }
}

7.两数共同因子个数

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
分析:

#include <bits/stdc++.h>

using namespace std;


main()
{
    long long int x,y,g;
    cin>>x>>y;
    int count=0;
    g=__gcd(x,y);
    for(int i=1; i*i<=g; i++)
    {
        if(x%i==0) count+=2;
        if(i*i==g) count--;
    }


    cout<<count;

}

8.取幂求余

Description
给定A,B,C,计算A^B%C,这里A^B代表A的B次方。
Input
输入数据有多组,每组数据一行,有3个正整数分别为A,B和C,1<=A,B,C<=1000000000
Output
输出A^B%C的值
Sample Input
2 3 5
8 2 10
Sample Output
3
4

分析:用公式直接求就好,因为没有很大的数来计算,也不知道这样写行不行,这里用到了pow函数,用法是pow(base,exponent)

#include <bits/stdc++.h>

using namespace std;

main()
{

    int a,b,c;
    while(cin>>a>>b>>c)
    {
        a=a%c;
        a=pow(a,b);
        a=a%c;
        cout<<a<<endl;
    }

}

!!pow函数

但是后来评论有说到数比较到,而且pow返回浮点数会有误差,这里我是没发现的(第一次认识pow函数),之后去查了一下,pow的返回值类型是double类型,表示计算结果的浮点数。

!!平方取余的方法

之后就在网上找到了别的做这道题的方法,这个用到的是a^b=((a^(b/n))^n)*a^(b%n),

当n=2时,a^b=(a^(b/2))*(a^(b/2))*a^(b%2),

即为(a^b)%mod=(a^(b/2))%mod*(a^(b/2))%mod*a^(b%2)%mod,

所以当b是偶数时,就可以看作是(a^b)%mod=(a*a^(b))%mod,

若a=a*a,那么b=b/2,这样递归下来就会简便很多,

而当b是奇数时,只要把它变成偶数就好,这个方法真的是太强了!!

#include <bits/stdc++.h>

using namespace std;

long long m(long long a,long long b,long long mod)
{
    long long ans=1;
    while(b)
    {
        if(b%2==1)
        {
            b--;
            ans=ans*a%mod;
        }
        a=a*a%mod;
        b=b/2;
    }
    return ans;
}




main()
{

    long long a,b,c;
    while(cin>>a>>b>>c)
    {
        cout<<m(a,b,c)<<endl;
    }

}

9.库特的数学题

Description
库特很喜欢做各种高深莫测的数学题,一天,她在书上看到了这么一道题。
a[1]=6,a[2]=18;a[n]=2*a[n-1]+3*a[n-2](n>=3),对于给出的某个数字n,求a[n]。
库特一想这道题太简单了,可是看到n的范围是(n<=1e18),
对于这么大范围的数,库特不知道该怎么做了,聪明的你,快来帮帮库特解决这个问题吧。
(由于答案可能很大,请将答案对1e9+7(即1000000007)取模)。
Input
一个整数n(1<=n<=1e18)
Output
a[n]对1e9+7取模后的答案
Sample Input
5
Sample Output
486
分析:由于n由n-1和n-2计算得出,所以要从3开始算到n,由于可能会出现溢出。所以在计算的时候直接就对a[i]求余

在网上还看到了另一种解法,推导的推导公式是(2*3^n)%1e9+7但是在我看来考试的时候是没有时间和精力去推导公式的,所以还是用了最原始的方法

#include <bits/stdc++.h>

using namespace std;

main()
{
   long long int n,i;
   cin>>n;
   long long int a[n];
   a[1]=6;
   a[2]=18;
   for(i=3;i<=n;i++)
   {
       a[i]=(2*a[i-1]%1000000007+3*a[i-2]%1000000007)%1000000007;
   }
   cout<<a[n];

}

10.异或方程解的个数

Description
ljw这几天给大一同学讲课的时候,觉得自己太菜了,于是他做了一道无聊的数学题,
但是他觉得这题太难了,所以他把问题交给了聪明的你,你能帮他解决这个问题吗?

问题如下:
给你一个方程:n−(n^x)−x=0 (其中 ^ 表示两个数异或,并不是表示幂次符号哦)
现在给你n的值,问有多少种x的取值使得方程成立(数据保证n在2的30次方范围内)
Input
多组输入数据(不超过2000000组)
每组输入数据包含一个整数n,含义如题。
Output
对于每组输入数据,你需要输出一个整数,表示解的个数。
Sample Input
0
2
Sample Output
1
2

分析:没怎么想明白这个题,只想到了用左移运算符去异或,然后在网上搜索学到了要当n的第i为为0时,x的也得为0,如果是1的话就随便了,我想到的是把式子变换成n-x=n异或x,当当n的第i为为1时,根据同0异1原则,和相减是一样的,但是当是0是,就不一样了

#include <bits/stdc++.h>

using namespace std;

main()
{

   long long int n,i,cnt;
    while(cin>>n)
    {
        cnt=0;
        for(i=0;i<31;i++)
        {
            if(n&1<<i) cnt++;
        }
        cnt=1<<cnt;
        cout<< cnt <<endl;
    }
}

  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值