约数
- 每一个数可以拆分成约数的乘积。
- 对每一个数,其约数成对出现。
- 对每一个数的每一个约数,也可以拆分成质因数的乘积
如 果 N = p 1 c 1 ∗ p 2 c 2 ∗ . . . ∗ p k c k 则 其 约 数 个 数 : ( c 1 + 1 ) ∗ ( c 2 + 1 ) ∗ . . . ∗ ( c k + 1 ) 约 数 之 和 : ( p 1 0 + p 1 1 + . . . + p 1 c 1 ) ∗ . . . ∗ ( p k 0 + p k 1 + . . . + p k c k ) 其 中 约 数 之 和 可 转 化 为 等 比 数 列 。 如果 N = p_1^{c_1} * p_2^{c_2} * ... *p_k^{c_k}\\ 则其约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)\\ 约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck) \\其中约数之和可转化为等比数列。 如果N=p1c1∗p2c2∗...∗pkck则其约数个数:(c1+1)∗(c2+1)∗...∗(ck+1)约数之和:(p10+p11+...+p1c1)∗...∗(pk0+pk1+...+pkck)其中约数之和可转化为等比数列。
-
试除法求约数
- 题目来源:Acwing 869:试除法求约数
- 时 间 复 杂 度 O ( n l o g n ) 时间复杂度O(nlogn) 时间复杂度O(nlogn)
#include<iostream> #include<cmath> #include<vector> #include<algorithm> using namespace std; const int INF = 0x3f3f3f3f; int a[110]; //求约数:质因数分解,正整数的约数也可以被质数的幂次和得到 // //试除法;暴力 void get_yueshu(int n) { vector<int> ans;//下面测出来的 for(int i = 0; i < n; i++) { for(int j = 1; j <= sqrt(a[i]); j++) { if(a[i] % j == 0) { ans.push_back(j); if(j*j != a[i]) ans.push_back(a[i]/j); //cout<<j; } } sort(ans.begin(), ans.end()); for(int i = 0 ; i < ans.size(); i++) cout<<ans[i]<<" "; cout<<endl; ans.clear(); } } int main() { int n; cin>>n; for(int i = 0; i < n; i++) cin>>a[i]; get_yueshu(n); // int num = 0; // for(int i = 1; i <= sqrt(2000000000); i++) // if(2000000000 % i == 0) num+=2; // cout<<num; //110个约数最多 return 0; }
-
求约数个数
- 将 N 质 因 数 分 解 : N = p 1 c 1 ∗ p 2 c 2 ∗ . . . ∗ p k c k , 则 约 数 个 数 : ( c 1 + 1 ) ∗ ( c 2 + 1 ) ∗ . . . ∗ ( c k + 1 ) 将N质因数分解:N = p_1^{c_1} * p_2^{c_2} * ... *p_k^{c_k},则约数个数:(c_1 + 1) * (c_2 + 1) * ... * (c_k + 1) 将N质因数分解:N=p1c1∗p2c2∗...∗pkck,则约数个数:(c1+1)∗(c2+1)∗...∗(ck+1)
- 题目来源:Acwing 870:求约数个数
#include<iostream> #include<vector> #include<utility> #include <unordered_map> using namespace std; // typedef pair<int, int> PII; // const int N = 2e9; const int mod = 1e9+7; // vector<PII> res; int main() { cin.tie(0),cout.tie(0); unordered_map<int, int> prime_num; int n; cin>>n; //错误写法:因为乘积之后再拆分质因数,这里用先分别算乘积之前的质因数,若每个质因数拆掉后,乘,则eg:第一个拆了3个2,第二个拆了4个2,理应是2^5共(0~7)8中选择,然而在此代码中却变成了:3*4=12 //这只适用于单个数,分解(即拆掉本最外层循环) // long long ans = 1; //结果 // for(int i = 0; i < n ; i++) // { // int x; // cin>>x; // for(int j = 2; j <= x / j; j++) // { // int tmp = 0; // while(x % j == 0) // { // tmp++; // x /= j; // } // ans = ans * (tmp + 1) % mod; // } // if(x > 1) ans = ans * (2) % mod; // } // cout<<ans; for(int i = 0; i < n ; i++) { int x; cin>>x; for(int j = 2; j <= x / j; j++) { while(x % j == 0) { prime_num[j]++; x /= j; } } if(x > 1) prime_num[x]++; } long long ans = 1; for(auto c : prime_num) ans = ans* (c.second+1) %mod; //在这里*=和 = *不等价... cout<<ans; }
-
求约数之和
- 即 : ( p 1 0 + p 1 1 + . . . + p 1 c 1 ) ∗ . . . ∗ ( p k 0 + p k 1 + . . . + p k c k ) 即:(p_1{^0} + p_1{^1} + ... + p_1^{c_1}) * ... * (p_k^0 + p_k^1 + ... + p_k^{c_k}) 即:(p10+p11+...+p1c1)∗...∗(pk0+pk1+...+pkck)
- 以上公式可转为等比数列求和公式,再求积,注意自定义
pow()
函数,避免数据过大溢出问题无法处理。 - 也可用
t = 1;---> t = p*t + 1 --- > t = p(pt+1)+1 --->t = p^2*t + pt + 1.....t = p^a + p^(a-1)...+p^0
- 题目来源:Acwing 871:求约数之和
#include<iostream> #include<vector> #include<utility> #include<cmath> #include<unordered_map> using namespace std; // typedef pair<int, int> PII; // const int N = 2e9; const int mod = 1e9+7; // vector<PII> res; int main() { cin.tie(0),cout.tie(0); unordered_map<int, int> prime_num; int n; cin>>n; for(int i = 0; i < n ; i++) { int x; cin>>x; for(int j = 2; j <= x / j; j++) { while(x % j == 0) { prime_num[j]++; x /= j; } } if(x > 1) prime_num[x]++; } long long ans = 1; for(auto c : prime_num) { long long a = c.first, x = c.second; // long long dengbi = (pow(a, x+1) - 1 ) / (a-1);//不行,溢出了可能pow(),除非自定义pow函数,除mod。 // ans = ans%mod * dengbi%mod; long long t = 1; while(x--) t = (t*a + 1)%mod; //t = p+1-> t = p^2+p+1-> t = p^3 + p^2 + p +1... ans = (ans * t)%mod; } cout<<ans%mod; }
-
最大公约数问题
- 欧几里得算法(辗转相除法): d ∣ a , d ∣ b − − > d ∣ ( a + b ) − − > d ∣ ( a x + b y ) d|a, d|b --> d|(a+b) --> d|(ax+by) d∣a,d∣b−−>d∣(a+b)−−>d∣(ax+by)
- 题目来源:Acwing 872:求最大公约数
#include<iostream> using namespace std; int gcd(int a, int b) { return b == 0 ? a: gcd(b, a%b); } int main() { int n; cin>>n; for(int i = 0; i < n ; i++) { int x, y; cin>>x>>y; cout<<gcd(x, y)<<endl; } }