见识

四方定理:所有自然数至多只要用四个数的平方和就可以表示。

 

费马定理:当整数n >2时,关于x, y, z的方程 x^n + y^n = z^n 没有正整数解。

 

顺序完全N叉树求先祖:a = (a + n - 2) / n。

 

同余定理:给定一个正整数m,如果两个整数a和b满足a-b能够被m整除,即(a-b)/m得到一个整数,那么就称整数a与b对模m同余,记作a≡b(mod m)。对模m同余是整数的一个等价关系。

 

威尔逊定理:若p为质数,则p可整除(p-1)!+1。

如:7为质数,则7可整除(7 - 1)! + 1 = 721,即721 % 7 == 0

 

欧拉函数:对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)例如φ(8)=4,因为1,3,5,7均和8互质。

 

欧拉定理:若n,a为正整数,且n,a互素,即gcd(a,n) = 1,则a^φ(n) ≡ 1 (mod n), 其中φ(n)为欧拉函数。

如:n = 5, a = 7. 因为与5互质的有1、2、3、4,即φ(5) = 4,则(7 ^ 4) % 5 = 2401 % 5 = 1。

 

三角形半周长 P=(a+b+c)/2,面积sqrt(P(P-a)(P-b)(P-c)),中线 Ma=sqrt(2(b^2+c^2)-a^2)/2。

 

  数据规模较小时求解,数据规模较大时特判。设L,K为任意自然数,L!=2时在[L,L+2K)区间内必不可能有超过K个素数。L=2时,也只有K=1,2,3时有超过K个素数。总结:遇到素数题不求素数才是基操。

 

求最小值时注意下限要大于0。

 

当109级出现乘法,必开long long 。牺牲精度的double范围比long long还大,可解决±261左右规模问题。

 

三个变量之间存在关系,其中一个由输入确定,必优化成单层循环。

 

素数筛法

    int sqrt_n = sqrt(b);
    is_prime[1] = 0;
    for (i = 2; i <= b; i++)
        is_prime[i] = 1;
    for (i = 2; i < sqrt_n; i++)
    {
        if (is_prime[i])
            for (j = i * i; j <= b; j += i)
                is_prime[j] = 0;
    }

  

卢卡斯定理:利用模运算快速求出二项式系数C(n,r),适用于不用模运算就无法求出其结果的、具有非常大的n和r的二项式系数。

LL PowMod(LL a, LL b, LL MOD)
{ //快速幂
    LL ret = 1;
    while (b)
    {
        if (b & 1)
            ret = (ret * a) % MOD;
        a = (a * a) % MOD;
        b >>= 1;
    }
    return ret;
}
LL fac[100005];
LL Get_Fact(LL p)
{ //初始化
    fac[0] = 1;
    for (int i = 1; i <= p; i++)
        fac[i] = (fac[i - 1] * i) % p;
}
LL Lucas(LL n, LL m, LL p)
{ //Lucas 定理
    LL ret = 1;
    while (n && m)
    {
        LL a = n % p, b = m % p;
        if (a < b)
            return 0;
        ret = (ret * fac[a] * PowMod(fac[b] * fac[a - b] % p, p - 2, p)) % p;
        n /= p;
        m /= p;
    }
    return ret;
}

  

卡特兰数(Catalan number)是 组合数学 中一个常出现在各种 计数问题 中的 数列。

​数列的前几项为:1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862,...

题目描述:

n 个元素进栈序列为:1,2,3,4,...,n,则有多少种出栈序列。

思路:

我们将进栈表示为 +1,出栈表示为 -1,则 1 3 2 的出栈序列可以表示为:+1 -1 +1 +1 -1 -1。

假设非法序列为 A,对应的序列为 B。每个 A 只有一个"第一个前缀和小于 0 的前缀",所以每个 A 只能产生一个 B。而每个 B 想要还原到 A,就需要找到"第一个前缀和大于 0 的前缀",显然 B 也只能产生一个 A。

#include <cstdio>
using namespace std;
long long catalan[1000005];
int main()
{
    int n;
    scanf("%d", &n);
    catalan[0] = catalan[1] = 1;
    for (int i = 2; i <= n; i++)
        for (int j = 0; j <= i - 1; j++)
            catalan[i] += catalan[j] * catalan[i - j - 1];
    printf("%lld\n", catalan[n]);
    return 0;
}

  

一段连续自然数异或结果

#include<bits/stdc++.h>
using namespace std;
#define md 1000000007
int yh (int n, int m)
{
    if (abs (n - m) < 4)
    {
        int n0 = min (n, m);
        int n1, n2, n3;
        if (abs (n - m) < 1)
            n1 = 0;
        else
            n1 = n0 + 1;
        if (abs (n - m) < 2)
            n2 = 0;
        else
            n2 = n0 + 2;
        if (abs (n - m) < 3)
            n3 = 0;
        else
            n3 = n0 + 3;
        return (n0 ^ n1) ^ (n2 ^ n3);
    }
    return yh (n - 1 - (n - 1) % 4, n - 1) ^yh (m - m % 4, m);
}
int main()
{
    int t;
    long long int ans = 0;
    scanf ("%d", &t);
    while (t--)
    {
        int n, m;
        scanf ("%d %d", &n, &m);
        ans += yh (n, m) % md;
        ans %= md;
    }
    printf ("%d", ans);
    return 0;
}

  

posted @ 2021-03-28 14:02  anyiya  阅读(35)  评论(0编辑  收藏  举报