Giả sử chúng ta có một số nguyên n, chúng ta phải tìm số nguyên dương nhỏ hơn hoặc bằng n, trong đó các số nguyên ít nhất có một chữ số xuất hiện nhiều hơn một lần.
Vì vậy, nếu đầu vào là n =200, thì đầu ra sẽ là 38
Để giải quyết vấn đề này, chúng tôi sẽ làm theo các bước sau -
-
Xác định một mảng a
-
để khởi tạo x:=n, khi x khác-0, hãy cập nhật x:=x / 10, thực hiện -
-
chèn x mod 10 vào cuối
-
-
đảo ngược mảng a
-
ret:=n
-
để khởi tạo w:=1, d:=1, khi w
-
d:=d * min (9, 10 - w + 1)
-
ret:=ret - d
-
-
Định nghĩa một hàm go (). Điều này không cần tranh cãi.
-
b:=(1 dịch chuyển theo chiều kim bit sang trái 10) - 1
-
để khởi tạo i:=0, khi i
-
để khởi tạo d:=i <1, khi d
-
ret:=ret - x
-
-
nếu ((1 dịch chuyển trái theo chiều dọc a [i]) theo chiều dọc bit AND b) khác 0, thì
-
b:=b XOR (1 bit dịch chuyển sang trái a [i])
-
-
Nếu không
-
trở lại
-
-
-
(giảm ret xuống 1)
-
-
Gọi hàm go ()
-
trả lại ret
Hãy cùng chúng tôi xem cách triển khai sau để hiểu rõ hơn -
Ví dụ
#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; }
Đầu vào
200
Đầu ra
38