题目描述:
给定 n n n 个正整数 a i a_i ai,对于每个整数 a i a_i ai,请你按照从小到大的顺序输出它的所有约数。
输入格式:
第一行包含整数 n n n。
接下来 n n n 行,每行包含一个整数 a i a_i ai。
输出格式:
输出共 n n n 行,其中第 i i i 行输出第 i i i 个整数 a i a_i ai 的所有约数。
数据范围:
1 ≤ n ≤ 100 , 1 ≤ a i ≤ 2 ∗ 1 0 9 1≤n≤100,1≤a_i≤2*10^9 1≤n≤100,1≤ai≤2∗109
输入样例:
2
6
8
输出样例:
1 2 3 6
1 2 4 8
#define _CRT_NO_SECURE_WARNINGS
#include
#include
#include
using namespace std;
vector<int> get_divisors(int n)
{
vector<int> res;
for (int i = 1; i <= n / i; ++i)
{
if (n % i == 0)
{
res.push_back(i);
if (i != n / i) res.push_back(n / i);
}
}
sort(res.begin(), res.end());
return res;
}
int main()
{
int n;
cin >> n;
while (n--)
{
int a;
cin >> a;
auto res = get_divisors(a);
for (auto e : res) cout << e << ' ';
cout << endl;
}
return 0;
}
整体时间复杂度: O ( n ) O(\sqrt n) O(n)
a a a 是 b b b 的约数 ⇒ b b b 是 a a a 的倍数
因此,要计算 1 1 1 ~ n n n 的所有约数,可以通过计算每个数在范围内的其倍数的数目来得到。
n 1 + n 2 + n 3 + . . . + n n ⇒ n log n \frac{n}{1} + \frac{n}{2} + \frac{n}{3}+ ... + \frac{n}{n} ⇒ n \log n 1n+2n+3n+...+nn⇒nlogn
所以每个数的平均约数为 log n \log n logn
快速排序的时间复杂度: O ( log n log log n ) O(\log n \log \log n) O(lognloglogn)
由算数的基本定理,可得 n n n 的唯一分解式:
n = P 1 r 1 ∗ P 2 r 2 ∗ . . . ∗ P k r k n = P_1^{r_1}*P_2^{r_2}*...*P_k^{r_k} n=P1r1∗P2r2∗...∗Pkrk
n n n 的约数个数公式:
φ ( n ) = ( r 1 + 1 ) ∗ ( r 2 + 1 ) ∗ . . . ∗ ( r k + 1 ) φ(n) = (r_1 + 1)*(r_2 + 1)*...*(r_k + 1) φ(n)=(r1+1)∗(r2+1)∗...∗(rk+1)
证明:
以 P 1 P_1 P1 为例,这个质数因子,可以选择 0 0 0 个,可以选择 1 1 1 个等等,最多可以选择 r 1 r_1 r1 个,就是有 r 1 + 1 r_1+1 r1+1 种选择的可能性,对 P 2 , P 3 , . . . , P k P_2,P_3,...,P_k P2,P3,...,Pk 也都是如此,根据乘法原理,所有的可能性就是 ( r 1 + 1 ) ∗ ( r 2 + 1 ) ∗ . . . ∗ ( r k + 1 ) (r_1+1)*(r_2+1)*...*(r_k+1) (r1+1)∗(r2+1)∗...∗(rk+1)。
例如:
180 = 2 2 ∗ 3 2 ∗ 5 180=2^2∗3^2∗5 180=22∗32∗5
φ ( 180 ) = ( 2 + 1 ) ∗ ( 2 + 1 ) ∗ ( 1 + 1 ) = 18 φ(180)=(2+1)∗(2+1)∗(1+1)=18 φ(180)=(2+1)∗(2+1)∗(1+1)=18
题目描述:
给定 n n n 个正整数 a i a_i ai,请你输出这些数的乘积的约数个数,答案对 1 0 9 + 7 10^9+7 109+7 取模。
输入格式:
第一行包含整数 n n n。
接下来 n n n 行,每行包含一个整数 a i a_i ai。
输出格式:
输出一个整数,表示所给正整数的乘积的约数个数,答案需对 109 + 7 109+7 109+7 取模。
数据范围:
1 ≤ n ≤ 100 , 1 ≤ a i ≤ 2 × 1 0 9 1≤n≤100,1≤a_i≤2×10^9 1≤n≤100,1≤ai≤2×109
输入样例:
3
2
6
8
输出样例:
12
#define _CRT_NO_SECURE_WARNINGS
#include
#include
using namespace std;
unordered_map<int, int> primes;
void divide(int n)
{
for (int i = 2; i <= n / i; ++i)
{
while (n % i == 0)
{
primes[i]++;
n /= i;
}
}
if (n > 1) primes[n]++;
}
int main()
{
int n;
cin >> n;
while (n--)
{
int a;
cin >> a;
divide(a);
}
long long res = 1;
for (auto t : primes) res *= (t.second + 1) % ((int)1e9 + 7);
cout << res << endl;
return 0;
}
约数之和的公式:
( P 1 0 + P 1 1 + P 1 2 + . . . + P 1 r 1 ) ∗ . . . ∗ ( P k 0 + P k 1 + P k 2 + . . . + P k r k ) (P_1^{0} + P_1^{1} + P_1^{2} + ... + P_1^{r_1})*...*(P_k^{0} + P_k^{1} + P_k^{2} + ... + P_k^{r_k}) (P10+P11+P12+...+P1r1)∗...∗(Pk0+Pk1+Pk2+...+Pkrk)
通过排列组列便可以得出所有约数之和
题目描述:
给定 n n n 个正整数 a i a_i ai,请你输出这些数的乘积的约数之和,答案对 1 0 9 + 7 10^9+7 109+7 取模。
输入格式:
第一行包含整数 n n n。
接下来 n n n 行,每行包含一个整数 a i a_i ai。
输出格式:
输出一个整数,表示所给正整数的乘积的约数之和,答案需对 1 0 9 + 7 10^9+7 109+7 取模。
数据范围:
1 ≤ n ≤ 100 , 1 ≤ a i ≤ 2 × 1 0 9 1≤n≤100,1≤a_i≤2×10^9 1≤n≤100,1≤ai≤2×109
输入样例:
3
2
6
8
输出样例:
252
#define _CRT_NO_SECURE_WARNINGS
#include
#include
using namespace std;
unordered_map<int, int> primes;
const int mod = 1e9 + 7;
void divide(int n)
{
for (int i = 2; i <= n / i; ++i)
{
while (n % i == 0)
{
primes[i]++;
n /= i;
}
}
if (n > 1) primes[n]++;
}
int main()
{
int n;
cin >> n;
while (n--)
{
int a;
cin >> a;
divide(a);
}
long long res = 1;
for (auto t : primes)
{
long a = t.first, b = t.second, e = 1;
while (b--) e = (e * a + 1) % mod;
res = res * e % mod;
}
cout << res << endl;
return 0;
}
欧几里得算法(辗转相除法)
设 a a a 为被除数, b b b 为除数,若 d ∣ a d|a d∣a 且 d ∣ b d|b d∣b,则: d ∣ ( a + b ) d|(a+b) d∣(a+b) d ∣ ( a ∗ x + b ∗ y ) d|(a∗x+b∗y) d∣(a∗x+b∗y)
余数 r = a − k ∗ b r = a - k*b r=a−k∗b ( k ∈ Z k∈Z k∈Z),由于 a a a 与 b b b 均为 d d d 的倍数,所以可以得到 d ∣ r d|r d∣r。
用 ( a , b ) (a,b) (a,b) 代表 a a a 和 b b b 的最大公约数,可得 ( a , b ) = ( b , r ) (a,b)=(b,r) (a,b)=(b,r)
故而:
(a,b) =(b, a % b)
题目描述:
给定 n n n 对正整数 a i , b i a_i,b_i ai,bi,请你求出每对数的最大公约数。
输入格式:
第一行包含整数 n n n。
接下来 n n n 行,每行包含一个整数对 a i , b i a_i,b_i ai,bi。
输出格式:
输出共 n n n 行,每行输出一个整数对的最大公约数。
数据范围:
1 ≤ n ≤ 1 0 5 , 1 ≤ a i , b i ≤ 2 × 1 0 9 1≤n≤10^5,1≤a_i,b_i≤2×10^9 1≤n≤105,1≤ai,bi≤2×109
输入样例:
2
3 6
4 6
输出样例:
3
2
#define _CRT_NO_SECURE_WARNINGS
#include
using namespace std;
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int main()
{
int n;
cin >> n;
while (n--)
{
int a, b;
cin >> a >> b;
cout << gcd(a, b) << endl;
}
return 0;
}