数论(蓝桥)

数论

说明:

数论题目的核心考点是:

1.最小公倍数gcd(a,b)

2.最大公约数lcm(a,b)

3.数学基本定理:因式分解

4.线性筛法求素数

5.约数个数定理

6.约数之和定理

1.等差数列
题目:

数学老师给小明出了一道等差数列求和的题目。

但是粗心的小明忘记了一部分的数列,只记得其中 N 个整数。

现在给出这 N 个整数,小明想知道包含这 N 个整数的最短的等差数列有几项?

分析:

根据题意可以知道,题目给我们的是等差数列中的任意的项,要求我们求等差数列最少有多少项。

根据等差数列的公式,只要我们知道了第一项和最后一项还有公差就可以求。这里不知道的就是公差d

求公差d,我们要求的是公差的最大公约数。这个数越大,我们得到的项数就越少。

#include <iostream>
#include <algorithm>

using namespace std;
const int N=100010;

int a[N];

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

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    
    sort(a,a+n);
    int d=0;
    for(int i=0;i+1<n;i++)d=gcd(a[i+1]-a[i],d);
    int k;
    if(d!=0)
        k=(a[n-1]-a[0])/d+1;
    else
        k=n;
    
    
    printf("%d",k);
    
    return 0;
}
2.X的因子链
题意:

输入正整数 X,求 X 的大于 1 的因子组成的满足任意前一项都能整除后一项的严格递增序列的最大长度,以及满足最大长度的序列的个数。

分析:

求的是X分解因素的因子组成的数,要求每一项都是前一项的倍数。求满足条件序列的个数,也就是求X的所有质因子的全排列问题,但是X的因子中有相同的,他们的顺序是一样的,需要除去。这里考的是因式分解和求质数。

代码:
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
typedef long long LL;
const int N=(1<<20)+10;

int primes[N],cnt;
int minp[N];
bool st[N];

/*
线性筛法的特点,每一个数都是被它的最小质因子筛掉的,因此可以利用这个特点快速求最小质因子
*/
void get_primes(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!st[i])
        {
            primes[cnt++]=i;
            minp[i]=i;
        }
        for(int j=0;primes[j]*i<=n;j++)
        {
            int t=primes[j]*i;
            st[t]=true;
            minp[primes[j]*i]=primes[j];
            if(i%primes[j]==0) break;
        }
    }
}

int main()
{
    get_primes(N-1);
    int x;
    int fact[30],sum[N];
    while (scanf("%d", &x) != -1)
    {
        int k = 0, tot = 0;
        while (x > 1)
        {
            int p = minp[x];
            fact[k] = p, sum[k] = 0; //分解质因子需要知道当前数的最小质因子
            while (x % p == 0)
            {
                x /= p;
                sum[k] ++ ;
                tot ++ ;
            }
            k ++ ;
        }

        LL res = 1;
        for (int i = 1; i <= tot; i ++ ) res *= i;
        for (int i = 0; i < k; i ++ )
            for (int j = 1; j <= sum[i]; j ++ )
                res /= j;

        printf("%d %lld\n", tot, res);
    }
    
    
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值