정수 n이 있다고 가정하고 n보다 작거나 같은 양의 정수의 수를 찾아야 합니다. 여기서 정수는 최소한 두 번 이상 나타나는 숫자를 가집니다.
따라서 입력이 n =200과 같으면 출력은 38이 됩니다.
이 문제를 해결하기 위해 다음 단계를 따릅니다. −
-
배열 정의 a
-
초기화 x :=n의 경우 x가 0이 아닌 경우 x :=x / 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