LightOJ1236 - Pairs Forming LCM (唯一分解定理)

Description

题目大意:就是求\(\sum_{i=1}^{n}{\sum_{j=i}^{n}{[lcm(i, j) == n]}}\)的结果。

思路

网上有篇博客对这题解释得非常好,记录一下。

看到这个式子,就想到应该和n的因子有关。
这里有一个结论
假设

\[n = p_1^{k_1} \cdot p_2^{k_1} ... p_n^{k_n} \]

设a, b都是n的因子,有

\[a = p_1^{x_1} \cdot p_2^{x_1} ... p_n^{x_n} \]

\[b = p_1^{y_1} \cdot p_2^{y_1} ... p_n^{y_n} \]

为了形式的统一,当因子不含质因子p时,令它的次数x=0。
就有

\[lcm(a, b)=p1^{\max(x_1, y_1)} \cdot p_2^{\max(x_2,y_2)}...p_n^{\max(x_n, y_n)} \]

\[\gcd(a, b)=p1^{\min(x_1, y_1)} \cdot p_2^{\min(x_2,y_2)}...p_n^{\min(x_n, y_n)} \]

所以对于\(lcm(a, b) == n\), 就要求这里的\(max(x_i, y_i) = k_i\),即这两个数必须有一个是\(k_i\),另一个可以取\([0, k_i]\)
对于每个\(p_i\),次数有\(2k_i + 1\)种选择。故一共有\(\prod_{i=1}^n{2k_i+1}\)种选择。由于题目要求i<=j,所以最后要除以2,再加上\(i=j=n\)的一种情况。
所以\(ans=\frac{\prod_{i=1}^n{2k_i+1}}{2}+1\)

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <string>
#include <stack>
#include <deque>
#include <cmath>
#include <iomanip>
#include <cctype>

#define endl '\n'
#define IOS std::ios::sync_with_stdio(0);
#define pb push_back
#define mp make_pair
#define seteps(N) fixed << setprecision(N) 

typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/

#define INF 0x3f3f3f3f
const int N = 1e7 + 10;
const double eps = 1e-8;
vector<int> prime;
bool isnp[N];


int main() {
    IOS;
    //FO;
    for(int i = 2; i < N; i++) {
        if(!isnp[i]) {
            prime.push_back(i);
            for(int j = 2 * i; j < N; j += i) {
                isnp[j] = 1;
            }
        }
    }
    int t;
    cin >> t;
    int cas = 0;
    while(t--) {
        ll n;
        cin >> n;
        ll ans = 1;
        ll tn = n;
        for(int i = 0; i < prime.size(); i++) {
            if(1ll * prime[i] * prime[i] > n) break;
            if(tn % prime[i] == 0) {
                int cnt = 0;
                while(tn % prime[i] == 0) {
                    tn /= prime[i];
                    cnt++;
                }
                ans = ans * (2 * cnt + 1);
            }
        } 
        if(tn != 1) {
            ans = ans * 3;
        }
        ans /= 2;
        ans += 1;
        
        
        cout << "Case " << ++cas << ": " << ans << endl;
    }
}

posted @ 2020-06-18 23:50  limil  阅读(113)  评论(0编辑  收藏  举报