สมมติว่าเรามีจำนวนเต็ม 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