Akvicor
Akvicor
发布于 2019-05-26 / 4 阅读
0
0

约数定理(约数个数定理,约束和定理)

约数个数定理可以计算出一个数约数的个数

约数个数定理

对于一个大于1正整数n可以分解质因数:

则n的正约数的个数就是

其中的指数。

定理简证

首先同上,n可以分解质因数 ,

由约数定义可知 的约数有: ,共 个;同理 的约数有 个...... 的约数有 个。

故根据乘法原理:n的约数的个数就是

例:正整数378000共有多少个正约数?

解:将378000分解质因数 由约数个数定理可知378000共有正约数 个。

实现

int f1(int n) {
    int r = (int) sqrt(1.0 * n);
    int sum = 0;
    if (r * r == n) {
        sum++;
        r--;
    }
    for (int i = 1; i <= r; i++)
        if (n % i == 0) {
            sum += 2;
        }
    cout << sum << endl;
}

// 稍快于f1
int f2(int n){
    int s = 1, r;
    for (int i = 2; i * i <= n; i++) {
        r = 0;
        while (n % i == 0) {
            r++;
            n /= i;
        }
        if (r > 0) {
            r++;
            s *= r;
        }
    }
    if (n > 1)
        s *= 2;
    cout << s << endl;
}

ll f3(ll n) {
    ll res=1;
    for(ll i=2;i*i<=n;i++){
        ll k=0;
        while(n%i == 0){
            n = n/i;
            k++;
        }
        if(k) res *= (k+1);
    }
    if(n != 1) res=res*2;
    if(res==1){
        if(n==1) return 1;
        else return 2;
    }
    cout << res << endl;
}

约数和定理

对于一个大于1正整数n可以分解质因数:

则由约数个数定理可知n的正约数有个,那么n的个正约数的和为

定理证明

若n可以分解质因数:

可知的约数有:

....

同理可知,的约数有:

实际上n的约数是在每一个的约数中分别挑一个相乘得来,可知共有种挑法,即约数的个数。

由乘法原理可知它们的和为

例:正整数360的所有正约数的和是多少?

解:

将360分解质因数可得

由约数和定理可知,360所有正约数的和为

可知360的约数有:

则它们的和为:

实现

ll qpow(ll x, ll y) {
    ll res = 1;
    while (y) {
        if (y & 1) res *= x;
        x *= x;
        y >>= 1;
    }
    return res;
}

ll getsum(ll n) {//返回n的约数和是多少.
    ll res = 1;
    for (ll i = 2; i * i <= n; i++) {
        ll k = 0;
        while (n % i == 0) {
            n = n / i;
            k++;
        }
        res *= ((1 - qpow(i, k + 1)) / (1 - i));
    }    //用等比数列公式(快速幂)算.
    if (n != 1) res *= (1 + n);
    cout << res << endl;
}

题目

求正约数应用例题hihocoder – 1284

直接暴力肯定不行, 所以想到求他们的约数, 则n的约数*m的约数/GCD(n,m)的约数就是答案. 求约数用以上定理.

ll getnum(ll n) { //得到a的约数个数.
    ll res = 1;
    for (ll i = 2; i * i <= n; i++) {
        ll k = 0;
        while (n % i == 0) {
            n = n / i;
            k++;
        }
        if (k) res *= (k + 1);
    }
    if (n != 1) res = res * 2;   //最后一个素数.
    if (res == 1) {    //本身就是素数或1.
        if (n == 1) return 1;
        else return 2;
    }
    return res;
}

void solve(ll n, ll m) {
    ll k = __gcd(m, n);
    ll num1 = getnum(n);
    ll num2 = getnum(m);
    ll num3 = getnum(k);
    ll t = __gcd(num3, num1 * num2);
    printf("%lld %lld\n", 1ll * num1 * num2 / t, 1ll * num3 / t);
}


评论