数学知识(1)

一、数论

二、组合计数

三、高斯消元

四、简单博弈论

一、数论

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

/*
质数(素数)是指在大于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 <iostream>
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)分解质因数——试除法

 

/*
//暴力 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 <iostream>

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)

/*
朴素筛法 时间复杂度可以看做nlogn
当i==2时,运算n/2次,类推,运算次数
n/2+n/3+...n/n==n(1/2+1/3+...1/n)==n*调和级数==n*(ln n + c)<nlogn
*/
#include <iostream>
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 <iostream>

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<<primes[j]*i<<endl;
            if (i % primes[j] == 0) break;
//这句话成立时,primes[j]一定是i的最小质因子,也一定是primes[j] * i的最小质因子
//这句话不成立时,primes[j]一定小于i的所有质因子,也一定是primes[j] * i的最小质因子
        }
    }
//总体思路是外层循环遍历每一个数,以每一个数为基准,遍历之前的质数来筛掉对应的合数
//一直遍历到当前的质数是此时外层循环遍历到的数的最小质因子为止
//内层循环的终止条件是要确保当前primes[j]是primes[j]*i的最小质因子,它最大只能
//等于i的最小质因子,如果更大一点它就不是primes[j]*i的最小质因子了
}

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

    get_primes(n);

    cout << cnt << endl;

    return 0;
}

(4)

 

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

using namespace std;

vector<int> get_divisors(int x)
{
    vector<int> 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)

/*
如果 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 <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>

using namespace std;

typedef long long LL;

const int N = 110, 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] ++ ;
            }

        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;
}

/*
如果 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 <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>

using namespace std;

typedef long long LL;

const int N = 110, 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] ++ ;
            }

        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 <iostream>
#include <algorithm>

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<<gcd(a, b)<<endl;
    }

    return 0;
}

 

#include <iostream>
#include <algorithm>

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<<gcd(a, b)<<endl;
    }

    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中学数学知识图谱NLP(自然语言处理)是指使用NLP技术来构建和应用中学数学知识图谱。数学知识图谱是一种将数学知识组织成图结构的方式,可以帮助学生和教师更好地理解和应用数学知识。 中学数学知识图谱NLP的主要目标是将自然语言文本转化为机器可理解的形式,然后通过构建数学知识图谱来整合、存储、检索和推理数学知识。通过这种方式,可以帮助学生更好地理解数学概念、规则和定理,提高数学学习的效果。 在中学数学中,存在大量的概念、公式和解题方法,而且它们之间常常存在复杂的关联关系。中学数学知识图谱NLP可以通过分析数学教材、试题和解题过程中的文字描述,从而识别出其中的数学概念、规则和定理,并将它们组织成一张具有层次结构和关联关系的图谱。这样一来,学生可以通过查询数学知识图谱来快速找到相关知识点,弥补知识的漏洞,提高解题的准确性和速度。 此外,中学数学知识图谱NLP还可以用于数学学习辅助系统的开发。通过将数学教材和试题中的自然语言转化为机器可理解的形式,系统可以自动生成数学学习资料、解题提示和错题分析等。这对于学生的自主学习和教师的教学辅助都具有积极的意义。 总之,中学数学知识图谱NLP利用NLP技术构建和应用数学知识图谱,可以帮助学生更好地理解和应用数学知识,提高数学学习的效果。它还可以为数学学习辅助系统的开发提供技术支持,提供个性化的学习资料和解题提示,促进学生的自主学习和教师的教学辅助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值