백준 2793 - 숫자의 힘

Updated:

Categories:

Tags: ,

백준 2793 - 숫자의 힘

풀이

어떤 숫자 N의 다음 숫자가 X가 된다고 하자.
그럼 N은 1 ~ X-1 의 최소공배수로 나눠 떨어지면서 X로는 나눠 떨어지지 않는 모든 수가 될 것이다.

1 ~ X-1의 최소공배수가 X로 나눠떨어지지 않아야 N의 다음숫자가 X가 될 수 있을 것이다. (이미 최소공배수가 X의 배수라면, X로도 나눠떨어지는 것이 당연하기 때문)
따라서 입력으로 주어진 A,B에 대하여 A ~ B의 수들 중 (1 ~ X-1의 최소공배수의 배수의 갯수)에서 (1 ~ X의 최소공배수의 배수의 갯수)를 빼면 1~X-1의 배수이면서 X의 배수가 아닌 수의 갯수를 찾을 수 있을 것이다.

여기서 X의 가능한 수는 $1 \sim 10^{17}$ 수들의 다음 수는 2 ~ 41 안에 들어간다. 따라서 X를 41까지 해주면 모든 수에 대해서 전부 해줄 수 있다.
(적어도 1 ~ 40의 최소공배수가 5342931457063200이고, 1 ~ 41의 최소공배수가 219060189739591200이므로 대충 41까지만 해주면 $10^{17}$까지 커버가 가능한 것을 알 수 있다.)

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <bits/stdc++.h>

#define endl "\n"
#define all(v) (v).begin(), (v).end()
#define For(i, a, b) for(int i=(a); i<(b); i++)
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define Bor(i, a, b) for(int i=(a)-1; i>=(b); i--)
#define BOR(i, a, b) for(int i=(a); i>=(b); i--)
#define ft first
#define sd second

using namespace std;
using ll = long long;
using lll = __int128_t;
using ulll = __uint128_t;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using ti3 = tuple<int, int, int>;
using tl3 = tuple<ll, ll, ll>;

template<typename T> using ve = vector<T>;
template<typename T> using vve = vector<vector<T>>;

template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }

const int INF = 987654321;
const int INF0 = numeric_limits<int>::max();
const ll LNF = 987654321987654321;
const ll LNF0 = numeric_limits<ll>::max();

const int mxn = 42;
int dp[mxn];

int strength(int n) {
    if(n == 2) return 1;
    int &ret = dp[n];
    if(ret != -1) return ret;

    for(int ni=2; ni<mxn; ni++) {
        if(n%ni != 0) return ret = strength(ni) + 1;
    }
    return ret;
}
ll gcd(ll a, ll b) {
    if(b == 0) return a;
    return gcd(b, a%b);
}

void solve() {
    memset(dp, -1, sizeof dp);
    ll a, b; cin >> a >> b;
    ll ans = 0;
    ll k=1;
    for(ll i=2; i<mxn; i++) {
        if(k%i == 0) continue;
        ll k_cnt = b/k - (a-1)/k;
        ll nk = k * (i/gcd(k,i));
        ll nk_cnt = b/nk - (a-1)/nk;
        ans += (k_cnt - nk_cnt) * (strength(i)+1);
        k = nk;
    }
    cout << ans << endl;
}

int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int TC=1;
//    cin >> TC;
    FOR(tc, 1, TC) {
//        cout << "Case #" << tc << ": ";
        solve();
    }


    return 0;
}

Leave a comment