约数
设a a a 为一个非零整数,b b b 是一个整数,如果存在一个整数q q q ,使得 b = a ∗ q b=a*q b = a ∗ q ,那么b b b 可被a a a 整除,记作 a ∣ b a|b a ∣ b ,b b b 是a a a 的倍数,a a a 是b b b 的约数
性质
1、如果a ∣ b a|b a ∣ b 且b ∣ c b|c b ∣ c ,那么a ∣ c a|c a ∣ c
2、a ∣ b a|b a ∣ b 且a ∣ c a|c a ∣ c ,对任意的整数x x x 和y y y ,有a ∣ ( b ∗ x + c ∗ y ) a|(b*x+c*y) a ∣ ( b ∗ x + c ∗ y )
3、a ∣ b a|b a ∣ b 等价于( a ∗ m ) ∣ ( b ∗ m ) (a*m)|(b*m) ( a ∗ m ) ∣ ( b ∗ m ) ,m不为零
4、设整数x x x 和 y y y 满足下式a ∗ x + b ∗ y = 1 a*x + b * y =1 a ∗ x + b ∗ y = 1 ,且a ∣ n a|n a ∣ n ,b ∣ n b|n b ∣ n ,那么( a ∗ b ) ∣ n (a*b)|n ( a ∗ b ) ∣ n
算术基本定理
任何一个大于1的自然数 N ,如果
N 不为质数,那么N 可以唯一分解成有限个质数的乘积
N = p 1 c 1 p 2 c 2... p m c m N = p_1^c1p_2^c2...p_m^cm
N = p 1 c 1 p 2 c 2... p m c m
其中c i ci c i 都是正整数
试除法求整数x的正约数集合
时间复杂度O ( n ∗ s q r t ( n ) ) O(n*sqrt(n)) O ( n ∗ s q r t ( n ) )
1 2 3 4 5 6 7 vector<int > res; int x;for (int i = 1 ; i<= x / i; i ++) if (x % i == 0 ) { res.emplace_back (i); if (i != x / i) res.emplace_back (x/i); }
倍数法求整数x的正约数集合
设有d ∣ n d|n d ∣ n 。
d = 1,d为1~n所有数的约数,数量为n;
d = 2,d为2,4,6,8……的约数,数量为n 2 \frac{n}{2} 2 n ;
d = 3,d为3,6,9……的约数,数量为n 3 \frac{n}{3} 3 n ;
……
d = n,数量为n n \frac{n}{n} n n ;
共有
n ∗ ( 1 + 1 2 + 1 3 + … … + 1 n ) = n ∗ l o g n n*(1+\frac{1}{2}+\frac{1}{3}+……+\frac{1}{n}) = n*logn
n ∗ ( 1 + 2 1 + 3 1 + …… + n 1 ) = n ∗ l o g n
时间复杂度为O(n*logn)
1 2 3 vector<int > res[N]; for (int i = 1 ; i<= n; i ++) for ( int j = 1 ; j <= n/ i; j ++) res[i*j].emplace_back (i);
约数个数
基于算术基本定理
N = p 1 c 1 p 2 c 2 . . . p m c m N = p_1^{c1}p_2^{c2}...p_m^{cm}
N = p 1 c 1 p 2 c 2 ... p m c m
N的约数
d = p 1 b 1 p 2 b 2... p m b m d = p_1^b1p_2^b2...p_m^bm
d = p 1 b 1 p 2 b 2... p m b m
b i bi bi 可以取 [0,ci],共ci+1种取法,约数个数总数为
∑ i = 1 n ( c i + 1 ) \sum_{i=1}^n(ci+1)
i = 1 ∑ n ( c i + 1 )
https://www.acwing.com/problem/content/description/872/
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <bits/stdc++.h> #include <unordered_map> using namespace std;const int N = 110 , mod = 1e9 +7 ;int t,n;int main () { cin>>t; unordered_map<int ,int > q; long long ans = 1 ; while (t--){ cin>>n; for (int i= 2 ; i <= n / i; i ++) if (n % i == 0 ){ while ( n % i == 0 ){ n /= i;q[i]++; } } if (n > 1 ) q[n]++; } for (auto i : q) ans = ans*(i.second + 1 ) % mod; cout<<ans<<'\n' ; }
约数之和
约数和为
( 1 + p 1 + p 1 2 + . . . + p 1 c 1 ) ∗ ( 1 + p 2 + p 2 2 + . . . + p 2 c 2 ) + . . . + ( 1 + p m + p m 2 + . . . + p m c m ) (1 + p_1 +p_1^2 + ...+p_1^{c1})*(1+p_2+p_2^2+...+p_2^{c2}) + ...+(1+p_m+p_m^2+...+p_m^{cm})
( 1 + p 1 + p 1 2 + ... + p 1 c 1 ) ∗ ( 1 + p 2 + p 2 2 + ... + p 2 c 2 ) + ... + ( 1 + p m + p m 2 + ... + p m c m )
N的约数d可以分解成
d = p 1 b 1 p 2 b 2 . . . p m b m d = p_1^{b1}p_2^{b2}...p_m^{bm}
d = p 1 b 1 p 2 b 2 ... p m bm
约数和公式得到的每一项都是d的形式
倍增法求约数和
1 2 3 4 5 6 7 8 9 vector<int > res[N]; for (int i = 1 ; i<= n; i ++) for ( int j = 1 ; j <= n/ i; j ++) res[i*j].emplace_back (i); for (int i = 1 ; i<= n; i++){ int ans = 0 ; for (int j = 0 ; j < res[i].size (); j ++) ans += res[i][j]; cout<<ans<<'\n' ; }
https://www.acwing.com/problem/content/description/873/
代码
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 <unordered_map> using namespace std;const int N = 110 , mod = 1e9 +7 ;int t,n;int main () { cin>>t; unordered_map<int ,int > q; long long ans = 1 ; while (t--){ cin>>n; for (int i= 2 ; i <= n / i; i ++) if (n % i == 0 ){ while ( n % i == 0 ){ n /= i;q[i]++; } } if (n > 1 ) q[n]++; } for (auto i : q) { auto p = i.first, s = i.second; long long cnt = 1 ; while (s--) cnt = (cnt * p + 1 ) % mod; ans = ans * cnt % mod; } cout<<ans<<'\n' ; }
GCD LCM
由算术基本定理可知,整数A = p 1 a 1 + p 2 a 2 + p 3 a 3 + . . . + p m a m A=p_1^{a_1}+p_2^{a_2}+p_3^{a_3}+...+p_m^{a_m} A = p 1 a 1 + p 2 a 2 + p 3 a 3 + ... + p m a m ,整数B = p 1 b 1 + p 2 b 2 + p 3 b 3 + . . . + p m b m B=p_1^{b_1}+p_2^{b_2}+p_3^{b_3}+...+p_m^{b_m} B = p 1 b 1 + p 2 b 2 + p 3 b 3 + ... + p m b m
对于A A A 和B B B 的约数d = p 1 0 − m i n ( a 1 , b 1 ) + p 2 0 − m i n ( a 2 , b 2 ) + p 3 0 − m i n ( a 3 , b 3 ) + . . . + p m 0 − m i n ( a m , b m ) d=p_1^{0-min(a_1,b_1)}+p_2^{0-min(a_2,b_2)}+p_3^{0-min(a_3,b_3)}+...+p_m^{0-min(a_m,b_m)} d = p 1 0 − min ( a 1 , b 1 ) + p 2 0 − min ( a 2 , b 2 ) + p 3 0 − min ( a 3 , b 3 ) + ... + p m 0 − min ( a m , b m )
则A A A 和B B B 的最大公约数g c d ( A , B ) = p 1 m i n ( a 1 , b 1 ) + p 2 m i n ( a 2 , b 2 ) + p 3 m i n ( a 3 , b 3 ) + . . . + p m m i n ( a m , b m ) gcd(A,B)=p_1^{min(a_1,b_1)}+p_2^{min(a_2,b_2)}+p_3^{min(a_3,b_3)}+...+p_m^{min(a_m,b_m)} g c d ( A , B ) = p 1 min ( a 1 , b 1 ) + p 2 min ( a 2 , b 2 ) + p 3 min ( a 3 , b 3 ) + ... + p m min ( a m , b m )
A A A 和B B B 的最小公倍数
l c m ( A , B ) = p 1 m a x ( a 1 , b 1 ) + p 2 m a x ( a 2 , b 2 ) + p 3 m a x ( a 3 , b 3 ) + . . . + p m m a x ( a m , b m ) lcm(A,B)=p_1^{max(a_1,b_1)}+p_2^{max(a_2,b_2)}+p_3^{max(a_3,b_3)}+...+p_m^{max(a_m,b_m)} l c m ( A , B ) = p 1 ma x ( a 1 , b 1 ) + p 2 ma x ( a 2 , b 2 ) + p 3 ma x ( a 3 , b 3 ) + ... + p m ma x ( a m , b m )
证得A ∗ B = g c d ( A , B ) ∗ l c m ( A , B ) A*B=gcd(A,B)*lcm(A,B) A ∗ B = g c d ( A , B ) ∗ l c m ( A , B )
如何直观求GCD——辗转相除法
g c d ( a , b ) = g c d ( a ( m o d b ) , b ) gcd(a,b) = gcd(a\pmod b,b)
g c d ( a , b ) = g c d ( a ( mod b ) , b )
设r ( a , b ) r(a,b) r ( a , b ) 为a a a ,b b b 所有公因数的集合,有g c d ( a , b ) = m a x ( r ( a , b ) ) gcd(a,b)=max(r(a,b)) g c d ( a , b ) = ma x ( r ( a , b ))
要证g c d ( a , b ) = g c d ( a , a − b ) gcd(a,b) = gcd(a,a-b) g c d ( a , b ) = g c d ( a , a − b ) ,只需证r ( a , b ) = r ( a , a − b ) r(a,b) = r(a,a-b) r ( a , b ) = r ( a , a − b )
根据整除的性质d ∣ b d|b d ∣ b 且d ∣ c d|c d ∣ c ,那么对任意的整数x x x ,y y y ,有d ∣ ( x ∗ b + y ∗ c ) d|(x*b+y*c) d ∣ ( x ∗ b + y ∗ c )
a , b a,b a , b 的公因数是a , a − b a,a-b a , a − b 的公因数,a , a − b , a a,a-b,a a , a − b , a 的公因数是a , b a,b a , b 的公因数
证得r ( a , b ) = r ( a , a − b ) r(a,b)=r(a,a-b) r ( a , b ) = r ( a , a − b ) ,则g c d ( a , b ) = g c d ( a , a − b ) gcd(a,b) = gcd(a,a-b) g c d ( a , b ) = g c d ( a , a − b )