math

数学知识

约数(因数)个数

  1. 因数总是成对出现的,一个在开根号左边,一个在右边,此时因数个数加二
  2. 特殊情况:有可能刚好等于开根号之后的数字,此时因数个数只加一
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <bits/stdc++.h>

    using namespace std;
    const int N = 1010;

    int n,a[N];

    int main(){
    cin >> n;
    for(int i=0;i<n;i++){
    cin >> a[i];
    }
    for(int i=0;i<n;i++){
    int cnt=0;
    for(int j=1;j*j<=a[i];j++){
    //因数总是成对出现的,一个在开根号左边,一个在右边,此时因数个数加二
    //特殊情况:有可能刚好等于开根号之后的数字,此时因数个数只加一
    if(a[i] % j == 0 && j*j != a[i]) cnt+=2;
    if(a[i] % j == 0 && j*j == a[i]) cnt+=1;
    }
    cout << cnt << "\n";
    }
    return 0;
    }

分解质因数

题目链接:分解质因数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <bits/stdc++.h>

using namespace std;
const int N = 1010;

int n,a[N];

int main(){
cin >> n;
while(n--){
int x;
cin >> x;
int m = x;
//循环到平方根
for(int i=2;i*i<=x;i++){
if(x%i == 0){
int cnt = 0;
while(x%i == 0){
x /= i;
cnt++;
}
cout << i << " " << cnt << "\n";
}
}
if(x > 1) cout << x << " 1" << "\n";
cout << "\n";
}
return 0;
}

欧几里得算法

$ gcd(a, b) = gcd(b, a mod b) $

欧拉函数

互质数:

两个数的公因数只有1的两个非零自然数,叫做互质数
1与任何数都互斥,自身与自身不互斥(公约数包括1和自身)

性质一:两个不同的质数是互质的。
性质二:一个质数,另一个不为它的倍数,这两个数为互质数。(较大数是质数的两个数是互质数)
性质三:相邻的两个自然数是互质数。
性质四:相邻的两个奇数是互质数。
性质五:最大公约数是1,两个数互质。

欧拉函数

定义:对于一个正整数n,n的欧拉函数ϕ(n)表示小于等于n中,与n互质的正整数的个数

分解质因数:N = $ p_1^{a_1} * p_2^{a_2} * …*p_n^{a_n} $

$ ϕ(N) = N(1- \frac{1}{p_1})(1- \frac{1}{p_2})…(1- \frac{1}{p_n}) $

用代码表示该公式时为了防止出现小数,用以下方式表示:
$ ϕ(N) = (\frac{N}{p_1})*(p_1 - 1) $

1
2
3
4
5
6
7
8
9
10
11
12
for(int i=2;i<=t/i;i++){
//判断i是不是t的质因子
if(t%i == 0){
res = (res/i)*(i-1);
while(t%i == 0){
t /= i;
}
}
}
//有没除尽的
if(t > 1) res = (res/t)*(t-1);
cout << res << endl;

性质1:如果n是质数,那么ϕ(n) = n−1,因为只有n本身与它不互质。

性质2:如果p,q都是质数,那么$ ϕ ( p ∗ q ) = ϕ ( p ) ∗ ϕ ( q ) = ( p − 1 ) ∗ ( q − 1 ) $.

快速幂

快速幂,二进制取幂,在O(logn)下求$ a^n $的方法

求 $ {a^b} % {p} $ 的值

做这个题前首先我们需要了解一下关于取余的公式
(a + b) % p = (a % p + b % p) % p
(a - b) % p = (a % p - b % p ) % p
(a * b) % p = (a % p * b % p) % p

$ a^b = a^{2^0+2^1+…+2^n(中的某几项)} $
ex. $ a^{10} = a^{(1010)_2} = a^{2^1+2^3} $

注意下述式子

$ a^{2^3} = (a^{2^2})^2 \ a^{2^0} = a $

第二个式子即可解释代码中的 a = a*a % p;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

LL a,b;
int p,n;

int main(){
cin >> n;
while(n--){
scanf("%d%d%d",&a,&b,&p);
LL res = 1;
while(b > 0){
// cout << b;
//求数末尾为1还是0
if(b & 1){
res = res * a % p;
}
a = a*a % p;
b = b >> 1; //注意这里要把移位后的值赋给b
}
cout << res << endl;
}
return 0;
}

矩阵快速幂

矩阵快速幂算法详细解析

矩阵快速幂主要是解决n很大的递推式问题

ex. f(n)=4f(n-1)+3f(n-2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
struct node
{
long long int m[10][10];
}ans,res;

//矩阵A * 矩阵B
node mul(node A,node B)
{
int i,j,k;
node temp;//定义一个临时矩阵,存放A*B的结果
for(i=0; i<n; i++)//先全部定义为0
{
for(j=0; j<n; j++)
{
temp.m[i][j] = 0;
}
}
for(i=0; i<n; i++)//矩阵相乘的代码
{
for(j=0; j<n; j++)
{
for(k=0; k<n; k++)
{
temp.m[i][j] += (A.m[i][k] * B.m[k][j])%666666;//取模
}
}
}
return temp;
}

//对个相同矩阵a的乘法
node quickpower(node a,long long n)
{
node c;
memset(c.m,0,sizeof(c.m));
int i;
for(i=0;i<2;i++) c.m[i][i]=1;//定义一个单位矩阵
while(n)
{
if(n & 1)
{
c=mul(c,a);
}
a=mul(a,a);
n=n>>1;
}
return c;
}
int main()
{
long long n,k;
cin>>n>>k;
memset(ans.m,0,sizeof(ans.m));

//这是构建常数矩阵,主要是其参数会随着递推式变化
ans.m[0][0]=4;
ans.m[0][1]=3;
ans.m[1][0]=1;
ans.m[1][1]=0;

n=n-2;//前俩个冒险者减去
ans=quickpower(ans,n);//求出常数矩阵的n-2次方

memset(res.m,0,sizeof(res.m));

//构建f[1] 和 f[2]
res.m[0][0]=233;
res.m[1][0]=4;

//相乘前:ans是常数矩阵的n-2次幂,mul矩阵是f[n-1] 和 f[n-2]
//相乘后:res矩阵是f[n] 和 f[n-1];
res=mul(ans,res);//求出最后的结果矩阵

//此时res.m[0][0] 即是 f[n]
k=k-res.m[0][0]; //减去最后的造成的总伤害

cout<<k<<endl;
return 0;
}


math
https://cs-lb.github.io/2024/03/29/algorithm_know/math/
作者
Liu Bo
发布于
2024年3月29日
许可协议