1. 程式人生 > 實用技巧 >NOI2020訓練題3 B 最小公倍數

NOI2020訓練題3 B 最小公倍數

\(n = 1\)

首先考慮\(n=1\),只能刪去一個數。

若不刪\(1\),刪\(2\),答案為\(3\)

若刪\(x(x \geq 3)\),答案為\(2\)

答案只可能為\(2\)\(3\)

若刪\(1\),若\(c = 3\),則剩下\(2,3\),答案為\(6\)

\(c > 3\),則剩下\(2,3,4, \dots\),答案為\(4\)

\(c \geq 3\)

考慮 \(c \geq 3\)

把每\(n\)個數當成一個集合,記為\(S_1,S_2,\dots,S_c\)

\(S_1\)集合內的數不刪光,任取\(x \in S_1\),\(2^k * x( k \in Z) \in S_2\)

此時\(lcm = 2^k *x \in S_2\),即\(lcm_{ans} \in S_2\)

但是刪光了\(S_1\)中的數後,任意兩個\(S_2\)中的數的\(lcm\)一定不在\(S_2\)中,因此\(lcm_{ans} > 2n\)

所以刪去\(1 \sim n\)為最佳。

考慮\(lcm(a,b)(a \leq b)\)的計算,\(lcm(a,b) = a * (\frac{b}{\gcd(a,b)})\),顯然我們要使\(t = \frac{b}{\gcd(a,b)}\)最小,因為\(t >1\),所以\(t = 2\)時最小,顯然\(b = 2a\)時,\(t = 2\)

\(c \geq 3\)時,\(b = 2a\)是可以取到的,\(a = n + 1, b = 2*(n + 1)\)即為所求,\(lcm = 2 * (n + 1)\)

\(c = 2\)

\(c=2\)時,\(b = 2a\)是取不到的,我們考慮\(d = b/a\)\(lcm(a,d * a) = ?\)

首先\(1 < d < 2\),然後令\(d = p/q \ (\gcd(p,q) = 1,p,q\in Z)\),\(lcm(a,d*a) = p * a\)

我們要使\(p\)儘量小,\(p = 3, q = 2\)為最小解。

選取$n + 1 \sim 2 * n $中最小的\(2\)

的倍數,乘\(3\)即可。

但是\(n = 4\)時,\(6 * \frac{3}{2} = 9 > 8\)不行,所以特判。


#include<bits/stdc++.h>
using namespace std;

long long n,c;

int main(){
    int T; scanf("%d",&T);
    while(T --){
        scanf("%lld%lld",&n,&c);
        if(n == 1){
            if(c == 3) printf("6\n");
            else printf("4\n");
            continue;
        }
        if(c == 2){
            if(n & 1) printf("%lld\n",(n + 1) * 3ll);
            else if(n == 4) printf("24\n");
            else printf("%lld\n",(n + 2) * 3ll); 
            continue;
        }
        if(c > 2){
            printf("%lld\n",(n + 1) * 2ll);
            continue;
        }
    }
    return 0;
}