zoukankan      html  css  js  c++  java
  • 2021暑假算法学习笔记(基础复习)#3

    2021-07-10

    昨天睡了懒觉,下午拿着三脚架出去拍了组延时,摸鱼一天。

    几天继续数论学习。

    欧拉函数

    首先分解质因子,然后运用公式算欧拉函数。

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    int n;
    
    int main()
    {
        cin >> n;
        while (n -- )
        {
            int x;
            cin >> x;
            
            int ans = x;
            for (int i = 2; i <= x / i; i ++ )
                if (x % i == 0)
                {
                    ans = ans / i * (i - 1);
                    while (x % i == 0) x /= i;
                }
            
            if (x > 1) ans = ans / x * (x - 1);
            
            cout << ans << endl;
        }
        
        return 0;
    }
    
    筛法求euler函数

    欧拉定理:若a与n互质,则有a^euler[n] mod n 同余1

    在线性筛的时候,求出euler

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    const int N = 1000010;
    
    int primes[N], cnt;
    bool st[N];
    int euler[N];
    int n;
    
    LL get_eulers(int n)
    {
        euler[1] = 1;
        for (int i = 2; i <= n; i ++ )
        {
            if (!st[i])
            {
                primes[cnt ++ ] = i;
                euler[i] = i - 1;
            }
            for (int j = 0; primes[j] <= n / i; j ++ )
            {
                st[primes[j] * i] = true;
                if (i % primes[j] == 0)
                {
                    euler[primes[j] * i] = euler[i] * primes[j];
                    break;
                }
                euler[primes[j] * i] = euler[i] * (primes[j] - 1);
            }
        }
        
        LL ans = 0;
        for (int i = 1; i <= n; i ++ ) ans += euler[i];
        
        return ans;
    }
    
    int main()
    {
        cin >> n;
        cout << get_eulers(n) << endl;
        
        return 0;
    }
    
    
    快速幂

    O(logk)求出a^k mod p

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    int n;
    int a, k, p;
    
    int qmi(int a, int k, int p)
    {
        int res = 1;
        while (k)
        {
            if (k & 1) res = (LL)res * a % p;
            k >>= 1;
            a = (LL)a * a % p;
        }
        
        return res;
    }
    
    int main()
    {
        scanf("%d", &n);
        while (n -- )
        {
            scanf("%d%d%d", &a, &k, &p);
            printf("%d
    ", qmi(a, k, p));
        }
        
        return 0;
    }
    
    快速幂求逆元

    求a mod p的乘法逆元

    a存在乘法逆元的充要条件是a与p互,当模数p是质数时,a的乘法逆元是a^(p - 2)

    //数据保证输入的p是质数
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    int n;
    int a, p;
    
    int qmi(int a, int k, int p)
    {
        int res = 1;
        while (k)
        {
            if (k & 1) res = (LL)res * a % p;
            k >>= 1;
            a = (LL)a * a % p;
        }
        
        return res;
    }
    
    int main()
    {
        scanf("%d", &n);
        while (n -- )
        {
            scanf("%d%d", &a, &p);
            
            LL ans = qmi(a, p - 2, p);
            if (a % p) printf("%d
    ", ans);
            else puts("impossible");
        }
        
        return 0;
    }
    
    扩展欧几里得算法

    对于一组数a b,求出一组x y 使得ax + by = gcd(a, b)

    当b == 0时候,a 和 0的最大公约数是a,此时a的系数x是1,0的系数取0是一组解。

    当b != 0时候,递归到b,a % b,此时需满足的方程是:

    [a / b]意思是a/b下取整

    b * y + (a - [a / b] * b) * x = d

    整理得到 a * x + b * (y - [a / b] * x) = d

    所以要更新一下y的值

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    int n;
    
    int exgcd(int a, int b, int &x, int &y)
    {
        if (!b)
        {
            x = 1, y = 0;
            return a;
        }
        int d = exgcd(b, a % b, y, x);
        y -= a / b * x;
        
        return d;
    }
    
    int main()
    {
        scanf("%d", &n);
        while (n -- )
        {
            int a, b, x, y;
            scanf("%d%d", &a, &b);
            exgcd(a, b, x, y);
            printf("%d %d
    ", x, y);
        }
        
        return 0;
    }
    
    线性同余方程
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    int n;
    
    int exgcd(int a, int b, int &x, int &y)
    {
        if (!b)
        {
            x = 1, y = 0;
            return a;
        }
        int d = exgcd(b, a % b, y, x);
        y -= a / b * x;
        
        return d;
    }
    
    int main()
    {
        scanf("%d", &n);
        while (n -- )
        {
            int a, b, x, y;
            scanf("%d%d", &a, &b);
            exgcd(a, b, x, y);
            printf("%d %d
    ", x, y);
        }
        
        return 0;
    }
    
    练习
    CodeForces-1454B

    考点 哈希表

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <unordered_map>
    
    using namespace std;
    
    const int N = 200010;
    
    int t;
    int n;
    int a[N];
    
    int main()
    {
        scanf("%d", &t);
        while (t -- )
        {
            int x;
            unordered_map<int, int > h, gnd;
            scanf("%d", &n);
            for (int i = 1; i <= n; i ++ )
            {
                scanf("%d", &a[i]);
                h[a[i]] ++ ;
                gnd[a[i]] = i;
            }
            
            int ans = 2e9;
            for (auto op : h)
                if (op.second == 1) ans = min(ans, op.first);
            
            if (ans != 2e9)
                printf("%d
    ", gnd[ans]);
            else puts("-1");
        }
        
        return 0;
    }
    
    CodeForces-1440C1

    类似脑筋急转弯一样,我们可以知道移动三步可以改变任意一个位置的值而其他值不改变。

    特判一下最后一行,最后一列,右下角的这些特殊情况。

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 110;
    
    int t;
    char g[N][N];
    int n, m;
    
    void pL(int i, int j, int k)
    {
        if (!k) printf("%d %d %d %d %d %d
    ", i, j, i + 1, j, i, j + 1);
        else if (k == 1) printf("%d %d %d %d %d %d
    ", i, j - 1, i, j, i + 1, j);
        else if (k == 2) printf("%d %d %d %d %d %d
    ", i - 1, j, i, j, i, j - 1);
        else printf("%d %d %d %d %d %d
    ", i - 1, j, i, j, i, j + 1);
    }
    
    int main()
    {
        cin >> t;
        while (t -- )
        {
            cin >> n >> m;
            for (int i = 1; i <= n; i ++ ) cin >> g[i] + 1;
            
            int ans = 0;
            for (int i = 1; i <= n; i ++ )
                for (int j = 1; j <= m; j ++ )
                    if (g[i][j] == '1') ans += 3;
            cout << ans << endl;
            for (int i = 1; i <= n; i ++ )
                for (int j = 1; j <= m; j ++ )
                    if (g[i][j] == '1')
                    {
                        if (i < n && j < m)
                            pL(i, j, 0), pL(i, j + 1, 1), pL(i + 1, j, 3);
                        else if (i == n && j == m)
                            pL(i, j, 2), pL(i - 1, j, 1), pL(i, j - 1, 3);
                        else if (i == n)
                            pL(i, j, 3), pL(i - 1, j, 0), pL(i, j + 1, 2);
                        else
                            pL(i, j, 1), pL(i, j - 1, 0), pL(i + 1, j, 2);
                    }
        }
        
        return 0;
    }
    
  • 相关阅读:
    Leetcode 1349 参加考试的最大学生数
    卡特兰数小结
    Leetcode 76 最小覆盖字串 (滑动窗口)
    Leetcode 5331.跳跃游戏
    实现对properties文件的有序读写
    Android日志框架darks-logs使用教程
    Android入门-Service-start,end,bind,unbind之间的区别
    Android实用代码七段(一)
    [转帖]自动调整TextView字体大小以适应文字长度
    apk,task,android:process与android:sharedUserId的区别
  • 原文地址:https://www.cnblogs.com/scl0725/p/14999340.html
Copyright © 2011-2022 走看看