数学知识(一):数论

质数

    在大于1的整数中,如果只包含1和本身这两个约数,就被称为质数,或者叫素数。

(1)质数判定

试除法

例题:试除法判定质数

给定 n 个正整数 ai,判定每个数是否是质数。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个正整数 ai。

输出格式

共 n 行,其中第 ii 行输出第 i个正整数 ai 是否为质数,是则输出 Yes,否则输出 No

数据范围

1≤n≤100,
1≤ai≤231−1

输入样例:

2
2
6

输出样例:

Yes
No

解题代码:

#include <iostream>
#include <algorithm>

using namespace std;

bool is_prime(int n)
{
    if(n<2) return false;//先判断是否大于1
    for(int i=2;i<=n/i;i++)//从2到n-是不是包含n的约数
        if(n%i==0)
            return false;
    return true;
}

int main()
{
    int n;
    cin >> n;

    while (n -- )
    {
        int x;
        cin >> x;
        if (is_prime(x)) puts("Yes");
        else puts("No");
    }

    return 0;
}

(2)分解质因数

1.试除法

n中最多只包含一个大于sqrt(n)的质因子

例题:分解质因数

给定 n 个正整数 aiai,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。

输入格式

第一行包含整数 n。

接下来 nn行,每行包含一个正整数 ai。

输出格式

对于每个正整数 ai,按照从小到大的顺序输出其分解质因数后,每个质因数的底数和指数,每个底数和指数占一行。

每个正整数的质因数全部输出完毕后,输出一个空行。

数据范围

1≤n≤100
2≤ai≤2×109

输入样例:

2
6
8

输出样例:

2 1
3 1

2 3

解题代码:

#include <iostream>
#include <algorithm>

using namespace std;

void divide(int n)
{
    //从小到大枚举n的所有约数
    for(int i=2;i<=n/i;i++)
        if(n%i ==0)//i一定是质数
        {
            int s=0;
            while(n%i==0)
            {
                n/=i;
                s++;
            }
            
            printf("%d %d\n",i,s);
        }
        
    if(n>1) printf("%d %d\n",n,1);
    puts("");
}

int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        int x;
        cin >> x;
        divide(x);
    }

    return 0;
}

2.筛质数

例题:筛质数

给定一个正整数 n,请你求出 1∼n 中质数的个数。

输入格式

共一行,包含整数 n。

输出格式

共一行,包含一个整数,表示 1∼n中质数的个数。

数据范围

1≤n≤106

输入样例:

8

输出样例:

4

 解法一:埃氏筛法

 解题代码:

#include <iostream>
#include <algorithm>

using namespace std;

const int N=1000010;

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

void get_primes(int n)
{
    for(int i=2;i<=n;i++)
    {
       if(!st[i])//当前数没有被筛过,说明是质数
       {
           primes[cnt++]=n;
           for(int j=i+i;j<=n;j+=i) st[j]=true;//把质数的倍数删掉
       }
       
      
    }
}

int main()
{
    int n;
    cin >> n;

    get_primes(n);

    cout << cnt << endl;

    return 0;
}

解法二:线性筛法

解题代码:

#include <iostream>
#include <algorithm>

using namespace std;

const int N=1000010;

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

void get_primes(int n)
{
    for(int i=2;i<=n;i++)
    {
       if(!st[i]) primes[cnt++]=i;//如果是质数就加入数表里面去
       for(int j=0;primes[j]<=n/i;j++)//从小到大枚举所有质数
       {
           st[primes[j]*i]=true;//每次把当前的质数与i的乘积筛掉
           if(i%primes[j]==0) break;//primes[j]一定是i的最小质因子
       }
       
      
    }
}

int main()
{
    int n;
    cin >> n;

    get_primes(n);

    cout << cnt << endl;

    return 0;
}

约数

 1.试除法求一个数的所有约数

例题:试除法求约数

给定 n 个正整数 aiai,对于每个整数 ai,请你按照从小到大的顺序输出它的所有约数。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个整数 ai。

输出格式

输出共 n 行,其中第 i 行输出第 i 个整数 ai的所有约数。

数据范围

1≤n≤100
2≤ai≤2×109

输入样例:

2
6
8

输出样例:

1 2 3 6 
1 2 4 8 

解题代码:

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

vector<int>get_divisors(int n)
{
    vector<int> res;//存答案的数组
    
    for(int i=1;i<=n/i;i++)
        if(n%i==0)//如果i是n的一个约数
        {
            res.push_back(i);
            if(i!=n/i) res.push_back(n/i);//防止n是i的平方,输出两个相同的数字
        }
    sort(res.begin(),res.end());
    return res;
}

int main()
{
    int n;
    cin>>n;
    
    while(n--)
    {
        int x;
        cin>>x;
        auto res=get_divisors(x);
        for(auto t:res) cout<<t<<' ';
        cout <<endl;
    }
    return 0;
}

 2.约数个数

例题:约数个数

给定 n个正整数 ai,请你输出这些数的乘积的约数个数,答案对 109+7取模。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个整数 ai。

输出格式

输出一个整数,表示所给正整数的乘积的约数个数,答案需对 109+7取模。

数据范围

1≤n≤100
1≤ai≤2×109

输入样例:

3
2
6
8

输出样例:

12

 解题:

#include <iostream>
#include <algorithm>
#include <unordered_map>

using namespace std;

typedef long long LL;

const int mod=1e9 + 7;

int main()
{
    int n;
    cin >>n;
    
    unordered_map<int ,int>primes;//存所有指数和底数
    while(n--)
    {
        int x;
        cin >>x;
        
        for(int i=2;i<=x/i;i++)
            while(x%i==0)
            {
                x/=i;
                primes[i]++;//i的质因数的指数+1
            }
        if(x>1) primes[x]++;
    }
    
    LL res=1;
    for(auto prime:primes) res=res*(prime.second +1)%mod;
    
    cout << res<<endl;
    
    return 0;
}

 

3.约数之和

例题: 约数之和

给定 n 个正整数 ai,请你输出这些数的乘积的约数之和,答案对 109+7取模。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个整数 ai。

输出格式

输出一个整数,表示所给正整数的乘积的约数之和,答案需对 109+7 取模。

数据范围

1≤n≤100
1≤ai≤2×109

输入样例:

3
2
6
8

输出样例:

252

解题: 

#include <iostream>
#include <algorithm>
#include <unordered_map>

using namespace std;

typedef long long LL;

const int mod=1e9 + 7;

int main()
{
    int n;
    cin >>n;
    
    unordered_map<int ,int>primes;//存所有指数和底数
    while(n--)
    {
        int x;
        cin >>x;
        
        for(int i=2;i<=x/i;i++)
            while(x%i==0)
            {
                x/=i;
                primes[i]++;//i的质因数的指数+1
            }
        if(x>1) primes[x]++;
    }
    
    LL res=1;
    for(auto prime:primes)
    {
       int p=prime.first,a=prime.second; //先枚举下每个质数,p为底数,a为指数
       LL t=1;//t表示总和
       //先求p的0次方加到p的a次方
       while(a--) t=(t*p+1)%mod;
       res=res*t%mod;
       
    }
    
    cout << res<<endl;
    
    return 0;
}

4.最大公约数:欧几里得算法(辗转相除法)

原理:

 

例题:最大公约数

给定 n 对正整数 ai,bi请你求出每对数的最大公约数。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一个整数对 ai,bi。

输出格式

输出共 n 行,每行输出一个整数对的最大公约数。

数据范围

1≤n≤105
1≤ai,bi≤2×109

输入样例:

2
3 6
4 6

输出样例:

3
2

解题代码: 

 

#include <iostream>

using namespace std;

int gcd(int a,int b)
{
    //b如果不是0的话,返回(b,a mod b),当b=0的时候,返回a(0可以整除任何数)
    return b?gcd(b,a%b):a;
}

int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        printf("%d\n",gcd(a,b));
    }
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值