티스토리 뷰

[Codeforces 1036C] Classy Numbers - 1800


문제 설명 : 

1부터 10^18까지의 수 중에서 0이 아닌 서로 다른 digit이 3번 이하로 등장하는 수가 몇 개 인지 세는 문제이다.


풀이 : 

수의 범위가 최대 10^18이기 때문에 매 쿼리마다 개수를 세는 것은 무리라고 생각해서 어떻게든 전처리를 한 다음에 O(1)이나 O(logN)만에 구해야 한다고 생각했다. 그래서 전처리로 3개의 자리수로 만들 수 있는 수들을 digit 3개, 10의자리 3개로 6중 for문을 구성하여 모두 벡터에다가 집어넣었다. 이렇게해도 최대 10*10*10*18*18*18=583만개이다. 정렬 뒤 unique연산을 취해준다. 그런 다음 쿼리의 L~R값을 구하기 위해서 1~R의 개수에서 1~L의 개수를 빼준다. 개수는 바이너리 서치를 통해서 해당 값보다 작은 원소의 개수가 몇 개인지 센다. 여기서 R값은 upper bound로 L값은 lower bound로 세주면 된다.


주의할 점 : 

-


배울 점 : 

경우의 수 문제라서 처음에 당연히 dp문제라고는 생각은 했는데 전처리로 숫자들을 모두 구해놓는다는 생각은 못했다. 전처리를 할 때도 for문으로 돌리면서 벡터에다 모두 집어넣은 뒤 나중에 바이너리 서치로 개수를 센다.


코드 : 


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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<functional>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<assert.h>
#include<stdlib.h>
#include<stack>
using namespace std;
/*********************Contest Template***********************/
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
typedef pair<int,int> Cord;
#define FASTIO ios_base::sync_with_stdio(false);cin.tie(0);
struct S{
    int a,b; S(){}S(int _a,int _b){
        a=_a;
        b=_b;
    }
    const bool operator<(const S &o) const{
        return a<o.a;
    }
};
priority_queue<int,vector<int>,greater<int>> mpq;
#define SPACE 0
#define NL 1
inline void showAll(vector<int> &v,int NL_or_space){ 
    //0 is space, 1 is NL
    for(int &here:v){
        printf("%d",here);
        printf("%c",(NL_or_space)?'\n':' ');
    }
}
/*********************Contest Template***********************/
// const int SIZE=
 
vector<ll> v;
 
ll cnt(ll find){
 
    ll l=-1,r=v.size();
 
    while(l+1<r){
        ll mid=(l+r)/2;
 
        if(v[mid]>find)
            r=mid;
        else l=mid;
    }
    return l;
}
 
int main(){
    int t;    scanf("%d",&t);
 
    ll scale[20]={1LL,};
    for(int i=1 ; i<=18 ; i++){
        scale[i]=scale[i-1]*10;
    }
    v.push_back(scale[18]);
 
    for(int d1=0 ; d1<=9 ; d1++){
        for(int d2=0 ; d2<=9 ; d2++){
            for(int d3=0 ; d3<=9 ; d3++){
                for(int s1=0 ; s1<18 ; s1++){
                    for(int s2=s1+1 ; s2<18 ; s2++){
                        for(int s3=s2+1 ; s3<18 ; s3++){
                            ll res=d1*scale[s1]+d2*scale[s2]+d3*scale[s3];
                            v.push_back(res);
                        }
                    }
                }
            }
        }
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
 
    while(t--){
        ll l,r;    scanf("%lld %lld",&l,&r);
        printf("%lld\n",cnt(r)-cnt(l-1));
    }
 
    
 
    return 0;
}
 
cs


'Problem Solving > Dynamic Programming' 카테고리의 다른 글

[CF 1155D] Beautiful Array  (0) 2019.08.20
[CF 1114D] Flood Fill  (0) 2019.07.25
[Codefocres 1061C] Multiplicity  (0) 2019.04.29
[Codeforces 1096D] Easy Problem  (0) 2019.04.21
[Codeforces 1113C] Sasha and a Bit of Relax  (0) 2019.03.10
댓글