唯一分解定理-你所喜欢的整数分解

 

 假如我们需要得到一个数的所有因子的个数:

譬如: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;
}

 

posted @ 2022-09-18 17:47  惣聪术  阅读(3)  评论(0)    收藏  举报