vector getDivisors(int n) {vector ans;for (int i = 2; i <= n / i; i++) {if (n % i == 0) {ans.push_back(i);if (i != n / i) {ans.push_back(n / i); // n == n/i,只需要存一个}}}return ans;
}
时间复杂度:O(n)O(\sqrt n)O(n)
约数和质因子并不是一个意思,但每个约数可以表示成质因子的乘积
算数基本定理:n=p1c1∗p2c2∗...∗pkckn=p_1^{c_1}*p_2^{c_2}*...*p_k^{c_k}n=p1c1∗p2c2∗...∗pkck的约数个数为:(c1+1)(c2+1)…(ck+1)(c_1+1)(c_2+1)…(c_k+1)(c1+1)(c2+1)…(ck+1),pkp_kpk为质因子
例子:12=22×3112=2^2×3^112=22×31,12的约数有1,2,3,4,6,12共6个,根据公式计算同样是(2+1)×(1+1)=6(2+1)×(1+1)=6(2+1)×(1+1)=6个
n的每个约数m都可以表示成m=p1b1∗p2b2∗...∗pkbkm=p_1^{b_1}*p_2^{b_2}*...*p_k^{b_k}m=p1b1∗p2b2∗...∗pkbk的形式,0<=bk<=ck0<=b_k<=c_k0<=bk<=ck,每个bkb_kbk有(ck+1)(c_k+1)(ck+1)种选法,于是就有(c1+1)(c2+1)…(ck+1)(c_1+1)(c_2+1)…(c_k+1)(c1+1)(c2+1)…(ck+1)个因数
我们分解质因子后,获取质因子的指数,最后套用(c1+1)(c2+1)…(ck+1)(c_1+1)(c_2+1)…(c_k+1)(c1+1)(c2+1)…(ck+1)即可
int getDivisorsNum(int n) {vector nums;for (int i = 2; i <= n / i; i++) {if (n % i == 0) {int num = 0;while (n % i == 0) {n /= i;num++;}// 获取质因子的指数nums.push_back(num);}}if(n > 1) nums.push_back(1);int ans = 1;for (int num : nums) {ans *= (num + 1);}return ans;
}

例子:12=22×3112=2^2×3^112=22×31,12的约数有1,2,3,4,6,12,约数之和为28,根据公式计算同样是(20+21+22)×(30+31)=28(2^0+2^1+2^2)×(3^0+3^1)=28(20+21+22)×(30+31)=28个
其中,p0+p1+p2+...+pn=(((p+1)×p+1)×p+1...)+1p^0+p^1+p^2+...+p^n=(((p+1)×p+1)×p+1...)+1p0+p1+p2+...+pn=(((p+1)×p+1)×p+1...)+1,一直循环n次
int getDivisorsSum(int n) {const int mod = 1e9 + 7;unordered_map primes;for (int i = 2; i <= n / i; i++) {if (n % i == 0) {while (n % i == 0) {n /= i;primes[i]++;}}}if (n > 1) primes[n] = 1;long long ans = 1;for (auto prime : primes) {int p = prime.first;int n = prime.second;// 计算sum = p^0 + p^1 + p^2 + ... + p^nlong long sum = 1;while (n >= 1) {sum = (sum * p + 1) % mod;n--;}ans = ans * sum % mod;}return ans;
}
如果d是a的约数,也是b的约数,则d是ax+by的约数,则有:gcd(a,b)=gcd(b,a%b)gcd(a,b)=gcd(b,a\%b)gcd(a,b)=gcd(b,a%b),gcd(a,0)=agcd(a,0)=agcd(a,0)=a
比如a=24,b=18,那么gcd(24,18)=6,gcd(18,24%18)=6
int gcd(int a, int b) {return b ? gcd(b, a % b) : a;
}
时间复杂度为O(logn)O(logn)O(logn)
上一篇:按描写对象归类的成语和词语
下一篇:有比喻的诗句