数学知识(1)

一、数论

二、组合计数

三、高斯消元

四、简单博弈论

一、数论

(1)质数的判定—— 试除法 O(sqrt(n));

数学知识(1)_第1张图片

/*
质数(素数)是指在大于1的自然数中,除了1和它本身以外不再有其他因数(约数)的自然数
1.严格大于1,本身大于等于2
2.除了1和自身之外没有其他因数,也就是只能整除这两个数
//暴力 O(n)
bool is_prime(int x)
{
    if (x < 2) return false;//严格大于1
    for (int i = 2; i < x; i ++ )//在2到n-1中存在某个数被x整除
        if (x % i == 0)
            return false;
    return true;
}
*/

#include 
using namespace std;
//优化 每个数的约数都是成对出现,如果i是n的约数,则n/i也是n的约数
bool is_prime(int x)
{
    if (x < 2) return false;
/*
可以枚举每一对约数中较小的那个数即可,较小的约数的范围是1到根号n(从2开始枚举)
也可以这样理解,从小到大枚举每个可能是约数的数,循环条件是这个可能是约数的数
小于与它配对的那个约数
i<=sqrt(x)不推荐,因为每次都要执行这个较慢的操作
i*i<=n也不推荐,当n大道接近int最大值时,i*i可能溢出变成负数
时间复杂度sqrt(n)
*/
    for (int i = 2; i <= x / i; i ++ )
        if (x % 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;
}
bool is_prime(int x)
{
    if (x < 2) return false;
    for (int i = 2; i <= x / i; i ++ )
        if (x % i == 0)
            return false;
    return true;
}

(2)分解质因数——试除法

数学知识(1)_第2张图片

 数学知识(1)_第3张图片

/*
//暴力 O(n)
void divide(int x)
{
    for (int i = 2; i <= x; i ++ )
/*
从小到大枚举x的所有数,这里没有枚举质元素,会有问题吗?不会,因为枚举到i时,
x已经把i前面的(2到i-1)质因子全部都除干净了,此时x % i == 0的话,x是i的倍数,
且不包含任何2到i-1中的质因子,i中也不包含任何2到i-1中的质因子,所以i是质数
*/
        if (x % i == 0)
        {
            int s = 0;
            while (x % i == 0) x /= i, s ++ ;
            cout << i << ' ' << s << endl;
        }
    if (x > 1) cout << x << ' ' << 1 << endl;
    cout << endl;
}
*/
/*
判定质数算法时间复杂度一定是根号n,但这道题时间复杂度不一定是根号n,
最好情况下是除一个数就除干净了,也就是除logn次
所以时间复杂度是logn到根号n之间
*/
#include 

using namespace std;

void divide(int x)
{
//任意大于1的自然数,最多只有一个大于sqrt(n)的质因子,反证法可证
//所以先在2到sqrt(n)的范围去找质因子
    for (int i = 2; i <= x / i; i ++ ){
/*
从2开始依次遍历,每次遍历到此时的i时,此时的x是已经把从2到i-1之间可能存在的质因子
全部除干净的x,如果这个时候的i仍然是此时的x的因数的话,那此时的i必然也是质数
*/      if (x % i == 0)
        {
            int s = 0;
            //每次遍历到这个质因子时,x将这个质因子除干净
            while (x % i == 0) x /= i, s ++ ;
            cout << i << ' ' << s << endl;
        }
    }
/*
如果此时已经把sqrt(n)之前的质因子全部除干净的n仍然大于1的话,那此时的n就是
那个大于sqrt(n)的质因子
*/
    if (x > 1) cout << x << ' ' << 1 << endl;
    cout << endl;
}

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

    return 0;
}
void divide(int x)
{
    for (int i = 2; i <= x / i; i ++ )
        if (x % i == 0)
        {
            int s = 0;
            while (x % i == 0) x /= i, s ++ ;
            cout << i << ' ' << s << endl;
        }
    if (x > 1) cout << x << ' ' << 1 << endl;
    cout << endl;
}

(3)

数学知识(1)_第4张图片

/*
朴素筛法 时间复杂度可以看做nlogn
当i==2时,运算n/2次,类推,运算次数
n/2+n/3+...n/n==n(1/2+1/3+...1/n)==n*调和级数==n*(ln n + c)
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 ++ )
    {//从前往后看,把每一个数的倍数筛掉,这样剩下的数一定是质数
//如果p没被筛掉,说明2到p-1中没有谁的倍数是p,也就是没有p的约数,因此p为质数
        if (!st[i]){ 
            primes[cnt ++ ] = i;
        }
        for (int j = i + i; j <= n; j += i)
            st[j] = true; 
    }
}

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

    get_primes(n);

    cout << cnt << endl;//输出cnt即可,不需要再加一,因为cnt已经++

    return 0;
}
/*
线性筛法  O(n) 数据级别为1e7时,比上个方法快一倍
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;
            if (i % primes[j] == 0) break;
        }
    }
}
*/
#include 

using namespace std;

const int N= 1000010;

int primes[N], cnt;// primes[]存储所有素数
bool st[N];// st[x]存储x是否被筛掉

void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
//n只会被它的最小质因子删掉
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= n / i; j ++ )
        {
//对于任意一个合数x,假设pj为x最小质因子,当外层循环的i枚举到x/pj时,x一定会被筛掉
//也就是说当i枚举到x时,在此之前i一定会枚举到比x小的x/pj,而这个时候,x就会被筛掉
//每次筛的数都是用最小质因子去筛的
//primes[j] <= n / i是因为primes[j] * i要<=n,这样st[primes[j] * i]才有效
//思路是从小到大枚举所有的质数,去这个质数去筛掉它一定作为最小质因子的那个合数
//循环条件是这个合数primes[j] * i<=n也就是primes[j] <= n / i
            st[primes[j]*i] = true;
            //cout<> n;

    get_primes(n);

    cout << cnt << endl;

    return 0;
}

(4)

数学知识(1)_第5张图片

 数学知识(1)_第6张图片

#include 
#include 
#include 

using namespace std;

vector get_divisors(int x)
{
    vector res;
    for (int i = 1; i <= x / i; i ++ )
    //约数成对出现,枚举较小约数即可
        if (x % i == 0)
        {
            res.push_back(i);
            if (i != x / i) res.push_back(x / 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 x : res) cout << x << ' ';
        cout << endl;
    }

    return 0;
}

(5)

数学知识(1)_第7张图片

数学知识(1)_第8张图片

/*
如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)
*/
#include 
#include 
#include 
#include 

using namespace std;

typedef long long LL;

const int N = 110, mod = 1e9 + 7;

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

    unordered_map primes;

    while (n -- )
    {
        int x;
        cin >> x;

        for (int i = 2; i <= x / i; i ++ )
            while (x % i == 0)
            {
                x /= i;
                primes[i] ++ ;
            }

        if (x > 1) primes[x] ++ ;
    }

    LL res = 1;
    for (auto p : primes) res = res * (p.second + 1) % mod;//(c1 + 1)

    cout << res << endl;

    return 0;
}

数学知识(1)_第9张图片

/*
如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)
*/
#include 
#include 
#include 
#include 

using namespace std;

typedef long long LL;

const int N = 110, mod = 1e9 + 7;

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

    unordered_map primes;

    while (n -- )
    {
        int x;
        cin >> x;

        for (int i = 2; i <= x / i; i ++ )
            while (x % i == 0)
            {
                x /= i;
                primes[i] ++ ;
            }

        if (x > 1) primes[x] ++ ;
    }

    LL res = 1;
    for (auto p : primes)
    {
        LL a = p.first, b = p.second;
        LL t = 1;
        while (b -- ) t = (t * a + 1) % mod;//(p1^0 + p1^1 + ... + p1^c1)
        res = res * t % mod;
    }

    cout << res << endl;

    return 0;
}

#include 
#include 

using namespace std;
// (a,b)==(b,a mod b)==(b,a - (a/b)*b)
// d能整除a,能整除b,则d也能整除a-c*b
// d能整除b,能整除a-c*b,则d也能整除能整除a-c*b+c*b==a
int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}


int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        int a, b;
        cin>>a>>b;
        cout<

数学知识(1)_第10张图片 数学知识(1)_第11张图片

#include 
#include 

using namespace std;
// (a,b)==(b,a mod b)==(b,a - (a/b)*b)
// d能整除a,能整除b,则d也能整除a-c*b
// d能整除b,能整除a-c*b,则d也能整除能整除a-c*b+c*b==a
int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}


int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        int a, b;
        cin>>a>>b;
        cout<

你可能感兴趣的:(#,数学知识,数学)