สมมติว่าเรามีจำนวนเต็ม n เราต้องหาจำนวนเต็มบวกที่น้อยกว่าหรือเท่ากับ n โดยที่จำนวนเต็มอย่างน้อยมีหลักเกิดขึ้นมากกว่าหนึ่งครั้ง
ดังนั้นหากอินพุตเท่ากับ n =200 เอาต์พุตจะเป็น 38
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
-
กำหนดอาร์เรย์
-
สำหรับการเริ่มต้น x :=n เมื่อ x ไม่ใช่ศูนย์ ให้อัปเดต x :=x / 10 ทำ -
-
แทรก x mod 10 ที่ส่วนท้ายของ a
-
-
กลับอาร์เรย์ a
-
ret :=n
-
สำหรับการเริ่มต้น w :=1, d :=1 เมื่อ w <ขนาดของ a อัปเดต (เพิ่ม w ขึ้น 1) ทำ -
-
d :=d * min(9, 10 − w + 1)
-
ret :=ret − d
-
-
กำหนดฟังก์ชัน go() นี้ไม่มีอาร์กิวเมนต์
-
b :=(1 กะบิตซ้าย 10) − 1
-
สำหรับการเริ่มต้น i :=0, เมื่อ i
-
สำหรับการเริ่มต้น d :=i <1 เมื่อ d
-
ret :=ret − x
-
-
ถ้า ((1 กะซ้ายระดับบิต a[i]) ระดับบิต AND b) ไม่ใช่ศูนย์ ดังนั้น
-
b :=b XOR (1 bitwise shift ซ้าย a[i])
-
-
มิฉะนั้น
-
กลับ
-
-
-
(ลดหย่อน 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