唯一分解定理-你所喜欢的整数分解
假如我们需要得到一个数的所有因子的个数:
譬如:6的所有因子是1,2,3,6
暴力去找,一定是O(n)的
如果我们只求素因子,我们只需要在√n的范围找,时间复杂度也就是O(√n)
但是我们还没有得到所有因子的个数
这里只需考虑乘法原理:假如在n中,pi的个数为ai个,那么加上不用它的情况即是ai+1种。所有的因子个数也就是∏(ai+1)
UVA294 约数 Divisors - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<iostream> #include<cstdio> #include<vector> #include<array> #include<utility> #include<cstring> using namespace std; typedef long long ll; const int maxn = 1e5 + 1e1; array<bool, maxn>isprime; vector<ll>prime; void sieve() { isprime.fill(true); isprime[0] = isprime[1] = false; for (ll i = 2; i < maxn; i++) { if (isprime[i])prime.emplace_back(i); for (const auto& j : prime) { if (i * j >= maxn)break; isprime[i * j] = false; if (i % j == 0)break; } } } pair<ll, ll> div(ll x) { pair<ll, ll>res(x, 1); for (const auto& i : prime) { if (x % i == 0) { ll cnt=0; while (x % i == 0) { x /= i; cnt++;} res.second*=cnt+1;//not use } if (x == 1ll)break; } return res; } int main() { sieve(); int t; cin >> t; while (t--) { ll l, r; cin >> l >> r; pair<ll, ll>ans(0, 0); for(ll i=l;i<=r;i++) { pair<ll, ll>res = div(i); if (res.second > ans.second)ans = res; } printf("Between %lld and %lld, %lld has a maximum of %lld divisors.\n", l, r, ans.first, ans.second); } return 0; }
利用整数分解,我们还可以解决阶乘的乘除问题。譬如n!(n<=数组能开的最大位)
n!显然可以分解到一个数组里,保存其素因子的个数
UVA10375 选择与除法 Choose and divide - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<cmath> #define maxn (int)(1e4+1e1) using namespace std; bool isprime[maxn]; vector<int>prime; void sieve() { memset(isprime, true, sizeof(isprime)); isprime[0] = isprime[1] = false; for (int i = 2; i <= maxn; i++)//筛出1e4的素数即可 { if (isprime[i])prime.push_back(i); for (auto j : prime) { if (i * j >= maxn)break; isprime[i * j] = false; if (i % j == 0)break; } } return; } int idx[maxn]; void solve(int n,int flag)//n!分解 { int res,ans; for (auto i : prime) { if (i > n)break; res = i; ans = 0; while (res <= n) { ans += n / res; res *= i; } idx[i] += ans*flag;//乘或除变成加或减 } return; } int main() { sieve(); int p, q, r, s; while (cin >> p >> q >> r >> s) { memset(idx, 0, sizeof(idx)); solve(p, 1), solve(s, 1), solve(r - s, 1); solve(q, -1), solve(r, -1), solve(p - q, -1); double ans = 1; /*for (auto i : prime) { cout << i << " " << idx[i] << "\n"; }*/ //逐一乘上素数 for (auto i : prime)//最大9973 { ans = ans * (double)pow(i, idx[i]);//i^0=1,不担心 } printf("%.5lf\n", ans); } return 0; }

浙公网安备 33010602011771号