정수 n이 있다고 가정하고 n보다 작거나 같은 양의 정수의 수를 찾아야 합니다. 여기서 정수는 최소한 두 번 이상 나타나는 숫자를 가집니다.
따라서 입력이 n =200과 같으면 출력은 38이 됩니다.
이 문제를 해결하기 위해 다음 단계를 따릅니다. −
-
배열 정의 a
-
초기화 x :=n의 경우 x가 0이 아닌 경우 x :=x / 10을 업데이트하고 -
를 수행합니다.-
끝에 x mod 10 삽입
-
-
배열 반전 a
-
렛 :=n
-
w :=1, d :=1 초기화의 경우, w
-
d :=d * min(9, 10 - w + 1)
-
렛 :=렛 - d
-
-
go() 함수를 정의합니다. 이것은 논쟁이 필요하지 않습니다.
-
b :=(1 비트 왼쪽 시프트 10) − 1
-
initialize i :=0의 경우, i
-
초기화 d :=i <1의 경우, d
-
렛 :=렛 − x
-
-
((1 비트 왼쪽 시프트 a[i]) 비트 AND b)가 0이 아닌 경우
-
b :=b XOR (1 비트 왼쪽 시프트 a[i])
-
-
그렇지 않으면
-
반환
-
-
-
(ret 1 감소)
-
-
go()
함수 호출 -
리턴 렛
이해를 돕기 위해 다음 구현을 살펴보겠습니다. −
예시
#include <bits/stdc++.h>
using namespace std;
int solve(int n) {
vector<int> a;
for (int x = n; x; x /= 10) a.push_back(x % 10);
reverse(a.begin(), a.end());
int ret = n;
for (int w = 1, d = 1; w < a.size(); ++w) {
d *= min(9, 10 − w + 1);
ret −= d;
}
auto go = [&]() {
int b = (1 << 10) − 1;
for (int i = 0; i < a.size(); ++i) {
for (int d = (i < 1); d < a[i]; ++d) {
int x = 0;
if ((1 << d) & b) ++x;
for (int j = i + 1; j < a.size(); ++j) x *= 10 − j;
ret −= x;
}
if ((1 << a[i]) & b)
b ^= (1 << a[i]);
else
return;
}
−−ret;
};
go();
return ret;
}
int main(){
cout << solve(200) << endl;
return 0;
} 입력
200
출력
38