数论唯一分解定理基础

唯一分解定理

1.定理介绍:

任何大于1的整数都可以表示成质因子的幂次相乘的形式,即
X = p 1 k 1 p 2 k 2 p 3 k 3 … … p n k n X=p_1^{k_1}p_2^{k_2}p_3^{k_3}……p_n^{k_n} X=p1k1p2k2p3k3pnkn
习惯上把质因数小的写前面
例如: 12 = 2 2 × 3 , 120 = 2 3 × 3 × 5 12=2^2×3,120=2^3×3×5 12=22×3,120=23×3×5


2.定理的几大应用

(一)因数个数和因数求和

根据组合数学的知识容易得出,每个质因子在因数中出现的个数是 [ 0 , k i ] [0,k_i] [0,ki],(0就表示没出现),所以因数总个数 S u m = ∏ i = 1 n ( k i + 1 ) = ( k 1 + 1 ) ( k 2 + 1 ) … … ( k n + 1 ) Sum=\prod_{i=1}^n(k_i+1)=(k_1+1)(k_2+1)……(k_n+1) Sum=i=1n(ki+1)=(k1+1)(k2+1)(kn+1)

同理可得所有因数的和的公式: S u m = ∏ i = 1 n ( ∑ j = 0 k j p i j ) = ( 1 + p 1 + p 1 2 + … … p 1 k 1 ) ( 1 + p 2 + p 2 2 + … … p 2 k 2 ) … … ( 1 + p n + p n 2 + … … p n k n ) Sum=\prod_{i=1}^n(\sum_{j=0}^{k_j}p_i^j)=(1+p_1+p_1^2+……p_1^{k_1})(1+p_2+p_2^2+……p_2^{k_2})……(1+p_n+p_n^2+……p_n^{k_n}) Sum=i=1n(j=0kjpij)=(1+p1+p12+p1k1)(1+p2+p22+p2k2)(1+pn+pn2+pnkn)

例题:LightOJ 1341

题意:给出T组a,b,求满足条件长方形(x,y)的个数,xy=a,且b<=x<y

做法:先用线性筛预处理所有的质数,对a进行唯一分解,根据乘法公式计算因数个数,由于题目说了不可能是正方形,所以直接对因数个数/2,再暴力减去小于b的因数个数

小声bb:如果数据是4000组1e12,5e5,那么每次暴力求小于b的因数个数时间复杂度 O ( T b ) O(Tb) O(Tb)不就是1e9级别的吗。。。是数据太水了吗?

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<queue>
#include<map>
#define ll long long
#define pb push_back
#define rep(x,a,b) for (int x=a;x<=b;x++)
#define repp(x,a,b) for (int x=a;x<b;x++)
#define W(x) printf("%d\n",x)
#define WW(x) printf("%lld\n",x)
#define pi 3.14159265358979323846
#define mem(a,x) memset(a,x,sizeof a)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int maxn=1e6+7;
const int INF=1e9;
const ll INFF=1e18;
int prime[maxn];
int primenum[maxn];
int m;
void prime_init()//质数线性筛
{
    m=0;
    rep(i,2,maxn)prime[i]=1;
    prime[0]=prime[1]=0;
    repp(i,2,maxn)
    {
        if (prime[i])
        {
            primenum[m++]=i;
        }
        for (int j=0;j<m&&i*primenum[j]<maxn;j++)
        {
            prime[i*primenum[j]]=0;
            if (i%primenum[j]==0)break;
        }
    }
}
int solve(ll x)//分解求因子数量
{
    int res=1;
    for (int i=0;i<m&&primenum[i]<=sqrt(x);i++)
    {
        int num=0;
        while(x%primenum[i]==0)
        {
            x/=primenum[i];
            num++;
        }
        res*=(num+1);//跟公式对比
    }
    if (x>1)res*=2;//说明还可以整除一个大质数,幂次肯定是1,所以×2,例如28=2^2*7
    return res;
}

int main()
{
    int t;
    ll a,b;
    scanf("%d",&t);
    prime_init();
    rep(K,1,t)
    {
        scanf("%lld%lld",&a,&b);
        if (b*b>a)printf("Case %d: %d\n",K,0);//说明不存在最小边长方形
        else
        {
            int ans=solve(a);
            ans/=2;
            repp(i,1,b)
            {
                if (a%i==0)ans--;
            }
            printf("Case %d: %d\n",K,ans);
        }
    }
    return 0;
}

例题2
LightOJ1336
题意:给出T个n,求1-n中有几个数字的因数之和是偶数
做法:根据因数求和公式可得 S u m = ∏ i = 1 n ( ∑ j = 0 k j p i j ) = ( 1 + p 1 + p 1 2 + … … p 1 k 1 ) ( 1 + p 2 + p 2 2 + … … p 2 k 2 ) … … ( 1 + p n + p n 2 + … … p n k n ) Sum=\prod_{i=1}^n(\sum_{j=0}^{k_j}p_i^j)=(1+p_1+p_1^2+……p_1^{k_1})(1+p_2+p_2^2+……p_2^{k_2})……(1+p_n+p_n^2+……p_n^{k_n}) Sum=i=1n(j=0kjpij)=(1+p1+p12+p1k1)(1+p2+p22+p2k2)(1+pn+pn2+pnkn)
那么显然如果这n项多项式中有一项是偶数的话,最后的因子和肯定是偶数,所以我们选择求奇数的个数,然后用n减去它得到最后答案

1.

当2作为质因子的时候,由于 2 , 2 2 , 2 3 2,2^2,2^3 2,22,23都是偶数,所以 ( 1 + 2 + 2 2 + … … 2 k 1 ) (1+2+2^2+……2^{k_1}) (1+2+22+2k1)肯定是奇数

2.

除去2的其他质数肯定都是奇数,所以当 k i k_i ki是偶数的时候, p i , p i 2 , p i n p_i,p_i^2,p_i^n pi,pi2,pin肯定都是奇数, ( 1 + p i + p i 2 + … … p i k i ) (1+p_i+p_i^2+……p_i^{k_i}) (1+pi+pi2+piki)肯定是奇数,因为多了个1在前面。当 k i k_i ki全是偶数的时候,才可以满足最后乘积是奇数,也就是说该数字是个完全平方数

最终就是
如果这个数是完全平方数,肯定符合因数和是奇数的条件的
还有一个就是如果这个数字包含2这个质因子,并且2的幂次是奇数次,所以导致这个数字不一定是完全平方数,解决办法就是除2,将2的幂次转化为偶数

所以最终答案就是 n − n − n 2 n-\sqrt{n}-\sqrt{n\over 2} nn 2n

/**
 *  Author1: low-equipped w_udixixi
 *  Author2: Sher丶lock
 *  Date :2019-09-19
 **/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<queue>
#include<map>
#define ll long long
#define pb push_back
#define rep(x,a,b) for (int x=a;x<=b;x++)
#define repp(x,a,b) for (int x=a;x<b;x++)
#define W(x) printf("%d\n",x)
#define WW(x) printf("%lld\n",x)
#define pi 3.14159265358979323846
#define mem(a,x) memset(a,x,sizeof a)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int maxn=2e6+7;
const int INF=1e9;
const ll INFF=1e18;
int main()
{
    int t;
    ll n;
    scanf("%d",&t);
    rep(K,1,t)
    {
        scanf("%lld",&n);
        printf("Case %d: %lld\n",K,n-(ll)sqrt(n)-(ll)sqrt(n/2));
    }
    return 0;
}

待更

数论中,唯一分解定理(Unique Factorization Theorem)也被称为质因数分解定理,它指出每个大于1的整数都可以唯一地表示为质数的乘积。在Python中,我们可以使用以下方法来实现唯一分解定理: 1. 首先,我们可以编写一个函数来判断一个数是否为质数。一个简单的方法是从2开始,逐个判断该数是否能被小于它的数整除,如果能整除,则不是质数。 2. 接下来,我们可以编写一个函数来获取一个数的所有质因数。我们可以从2开始,逐个判断该数是否能被2整除,如果可以,则将2添加到质因数列表中,并将该数除以2。然后再继续判断是否能被3整除,如果可以,则将3添加到质因数列表中,并将该数除以3。依此类推,直到该数变为1为止。 3. 最后,我们可以编写一个函数来实现唯一分解定理。该函数将调用上述获取质因数的函数,并将质因数列表返回。 下面是一个示例代码: ```python def is_prime(n): if n <= 1: return False for i in range(2, int(n**0.5) + 1): if n % i == 0: return False return True def get_prime_factors(n): factors = [] i = 2 while n > 1: if n % i == 0: factors.append(i) n //= i else: i += 1 return factors def unique_factorization(n): if n <= 1: return [] prime_factors = get_prime_factors(n) return prime_factors # 示例用法 number = 36 factors = unique_factorization(number) print(f"唯一分解定理:{number} = {' × '.join(map(str, factors))}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值