• 第一期寒假学习总结


      一个漫长的寒假不知不觉就过完了?总结一下学习的东西,这些天的重点主要放在了数论方面,刷题方面刷的也基本是关于数论方面的纯公式题,可能我太菜了,很多都要写到晚上凌晨1,2点才能肝出来,刷的题并没有很多估计二十多(好难QAQ),总之总结下我学的一些数论知识:

       

      1. 皮亚诺公理

          整个算术规则都是建立在 5 个基本公理基础之上的,这 5 个基本公理被称为皮亚诺公理。皮亚诺公理定义了自然数所具有的特性,具体如下:

    • 0是自然数;
    • 每个自然数都有一个后续自然数;
    • 0不是任何自然数的后续自然数;
    • 不同自然数的后续自然数不同;
    • 如果集合S包含了数字0,并且包含S中每一个数字的后续自然数,那么集合S就包含了所有的自然数。

      

      2. 算术基本定理和除法运算法则

         正如这个定理的名称所言,算术基本定理是数论中所有概念的核心。算术基本定理含义如下:任何一个大于1的整数都可以以某种特定的方式写成质数的乘积的形式(这种特定方式取决于乘积中质数的顺序)。例如,18 = 2 * 9, 1755 = 33 *5 * 13. 这个定理在几乎所有的数论运算法则中都扮演着十分重要的角色,例如求一个数的质数因子、最大公约数、除数的和等等。想要证明这个定理其实很简单,实际上它是欧几里得第一个定理的一个推论(下面小节会讨论到)。

    除法运算法则含义是说:给定两个整数a,b(b不等于0),那么存在两个整数q和r使得下面的等式成立:

    • a = bq + r, 0 <= r < b

    通常我们把q称为商,而把r称为余数。如果r = 0,那么我就说b整除a,并且表示为:b | a.

       3. 欧几里得定理

        数学中两个重要定理,被称为“欧几里德的第一定理(或欧几里德的引理)”和“欧几里德的第二定理(通常简称为”欧几里德定理“),内容如下:

    • 第一定理:p|ab => p|a or p|b。该定理的直接结论就是算术基本定理。
    • 第二定理:质数的数量是无限的。有很多简单的证明方法。

        虽然确实存在无限多的质数,但也应该记住,质数之间存在任意大的差值。换句话说,给定n的前提下,总是可以获得一些列的n个连续复合数。

        4. 最大公约数、最小公倍数和贝祖定理

        欧几里得算法是求两个数的最大公约数最常用的算法,而且也是一个很高效的算法,因为使用欧几里得算法求解两个数的最大公约数的算法步骤最多不会超过这两个数中较小的那个数的5倍。最大公约数通常使用圆括号表示—— (a,b) 表示a和b的最大公约数。类似地,最小公倍数通常使用方括号表示—— [a,b] 表示a和b的最小公倍数。

    • 如果 (a,b) = 1,即 [a,b] = ab,此时我们称a和b互质。
    • 如果 (a,b) = d,那么 (a/d,b/d) = 1。

        最大公约数和最小公倍数之间的关系可以由一个非常简单的等式来表示:(a,b) * [a,b] = ab. 该等式为我们提供了一种快速计算两个数的最小公倍数的方法。

        贝祖定理是说,如果 d = (a,b) 那么一定存在整数 x 和整数 y 满足 ax + by = d. (当然,如果存在的话,那么线性双变量方程的理论保证了无穷多解的存在性)。同样值得注意的是,k = d 是满足 ax + by = k 有一个关于 x 和 y 的解的最小正整数。

    指定 a 和 b,我们可以通过递归或迭代的方式实现扩展的欧几里得算法来求解满足等式 ax + by = d 的 x 和 y。(我理解能力有点差,这个是真的看了半天才弄明白一些)

        5.整数因式分解

        整数因子分解的最常用的算法是 Eratosthenes 筛选法。在分解N时,将质数扫描到 sqrt(N)就足够了。另外,如果我们需要对 1 到 N 之间的所有数字进行因式分解,则可以使用该算法的单次运行来完成此任务 - 对于 1 到 N 之间的每个整数 k ,我们可以保持一对映射——整除 k 的最小质数、最大倍数,(p,a)。k 的剩余质因子与 k/(pa) 的相似。

        6.线性同余方程组

        形如ax≡b (mod n)的方程式(x是未知数)称为线性同余。当且仅当存在整数x使得n | (ax-b)成立时,这样的方程组将有一个解,即ax -b = ny,y是整数,换句话说,ax + n(-y)= b。我们已经从Bezout的等式中得知,像这样的线性不定方程将只有在(a,n)的gcd(假设该值为d)整除b时才有解。在这种情况下,让b = dd',a = da',n = dn',所以我们有:

    • da'x + dn'( - y)= dd',其中gcd(a',n')= 1
    • 带入变量d
    • a'x + n'( - y)= d'。
    • 由于gcd(a',n') = 1,现在我们可以使用扩展的欧几里德的算法来找到a'x + n'( - y)= 1的解,然后将该解乘以d'得到对于a'x + n'( - y)= d'的解。

    注意,如果ax≡b(mod n)有一个解,则mod(n / d)有且仅有一个解。如果这个解是用x0表示的,那么mod n将恰好有d个解,由x0 + kn/d给出,其中0<= k。(这个也是写题目经常用到的一个定理,跟欧几里德算法有很大联系)

    记得的数论就这么多了先暂时列这么多吧,还有我有点想吐槽下我的电脑,在整个寒假重装了5次,装了4次GCC环境 有点绝望了,每次配置好SUB的C++编写环境电脑就出问题了,已经不想说话了。

    下面分享一些我有一点印象的题,对数论提高有些帮助。(挠破头皮)

    (有些部分参考了一些大佬的操作和分析,纯属分享)

    一.

    问题描述
      给定区间[L, R] , 请计算区间中素数的个数。

    输入格式
      两个数L和R。

    输出格式
      一行,区间中素数的个数。

    样例输入
    2 11

    样例输出
    5

    数据规模和约定
      2 <= L <= R <= 2147483647 R-L <= 1000000

    分析: 知道一般的素数筛法的应该都知道原理,这里其实就是模拟一下那里的筛法,简叙如下:

    1.预处理出[0,2147483647]内的所有素数
    2.用[0,r - l]来表示[l,r],找到对应关系
    3.利用筛法的思想进行筛数,比如第一个素数 2,[l,l+2]其中肯定有一个是2的倍数,找到起点,然后往后扫一遍筛掉即可
    4.考虑3的做法是否合理,因为 r - l的范围是1e6,时限上过不去的,考虑优化,我们可以想到其实我们可以在O(1)的时间内找到起点,只有几种情况:

    <1> 当素数p >= l, 我们只需将起点放在 p - l处即可
    <2> 否则,考虑l % p是否为0,如若为0,则就在0点,否则在 p - l % p处
    <3> 如果当前起点 + l为素数时,就要往后走p个单位
    ●5.O(n)统计可以

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 1e6 + 7;
    
    int m = (int) sqrt(2147483647+0.5) + 10;
    bool isp[maxn];
    int p[maxn/10];
    int len;
    
    void init() {
        isp[0] = isp[1] = true;
        for (int i = 2; i < m; i++) {
            if (!isp[i]) p[++len] = i;
            for (int j = 1; j <= len && p[j]*i < m; j++) {
                isp[i*p[j]] = true;
                if(i % p[j] == 0) break;
            }
        }
    }
    
    int main() {
        init();
        memset(isp,false,sizeof isp);
        int l,r;cin>>l>>r;
        int Len = r - l + 1;
        for (int i = 1; i <= len; i++) {
            int L;
            if(p[i] >= l) L = p[i] - l;
            else {
                if(l % p[i] == 0) L = 0;
                else L = p[i] - l%p[i];
            }
            if(l + L == p[i]) L += p[i];
            for (int j = L; j <= Len; j += p[i]) {
                isp[j] = true;
            }
        }
        int cnt = 0;
        for(int i = 0; i < Len; i++) {
            if (!isp[i]) cnt++;
        }
        if(l == 1) cnt--;
        cout<<cnt<<endl;
        return 0;
    }
    

      

    二.(一道英文题)

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 8066 Accepted Submission(s): 3418

    Problem Description
    The Sky is Sprite.
    The Birds is Fly in the Sky.
    The Wind is Wonderful.
    Blew Throw the Trees
    Trees are Shaking, Leaves are Falling.
    Lovers Walk passing, and so are You.
    …………………………..Write in English class by yifenfei

    Girls are clever and bright. In HDU every girl like math. Every girl like to solve math problem!
    Now tell you two nonnegative integer a and b. Find the nonnegative integer X and integer Y to satisfy X*a + Y*b = 1. If no such answer print “sorry” instead.

    Input
    The input contains multiple test cases.
    Each case two nonnegative integer a,b (0

    Output
    output nonnegative integer X and integer Y, if there are more answers than the X smaller one will be choosed. If no answer put “sorry” instead.

    Sample Input
    77 51
    10 44
    34 79

    Sample Output
    2 -3
    sorry
    7 -3

    Author
    yifenfei

    题意: ax+by = 1,给你a和b,问你让你求出一组数组,使得x > 0,并取最小,如果没有输出sorry

    分析: 无解的情况就是gcd(a,b) != 1,然后根据扩展欧几里得的性质,求得符合题意的x即可

    代码:

    #include<bits/stdc++.h>
    
    #define ll long long
    
    using namespace std;
    
    void egcd(ll a,ll b,ll &d,ll &x,ll &y) {
        if(!b) {
            d = a;x = 1;y = 0;
        } else {
            egcd(b,a%b,d,y,x);
            y -= x*(a/b);
        }
    }
    
    int main(){
        ios_base::sync_with_stdio(0);
        ll a,b;
        while (cin>>a>>b) {
            ll x,y,d;
            egcd(a,b,d,x,y);
            if(d != 1) {
                cout<<"sorry"<<endl;
            } else {
                if(x > 0) {
                    cout<<x<<' '<<y<<endl;
                } else {
                    while(x <= 0) {
                        x += b;
                        y -= a;
                    }
                    cout<<x<<' '<<y<<endl;
                }
            }
        }
        return 0;
    }
    

      

    暂时先是这两道试水题,以后有觉得好的再继续更新博客。

  • 相关阅读:
    hibernate---核心开发接口1(重点)
    hibernate--联合主键(了解+,掌握-)
    hibernate---table_Generator
    hibernate---ID生成策略
    hibernate 注解写在哪?
    hibernate学习笔记--可选的配置属性
    软件开发的硬约束【转载】
    (2016春) 作业7: 用户体验设计案例分析
    (2016春) 第一阶段优胜者
    (2016春) 作业6 :团队作业
  • 原文地址:https://www.cnblogs.com/xiangqi/p/10420892.html
Copyright © 2020-2023  润新知