差點AKdiv3www
首先這道題肯定不能暴力了啦。之后我們發現這道題其實跟數位dp非常的相像。那么數位dp的時候,一旦某一位變大了,那么后面的數字其實是隨便選的,因為不管怎么選,這個數字肯定是大於之前的數的。
比如122245與123***肯定不管怎么取*的數字肯定是比122245大的。
之后這道題又要取最小,我們可以想到從最后開始枚舉,因為修改的數位越小,那么肯定是越小的。
所以就能想到暴力枚舉每一位,如果出現了合法的答案就肯定是這個了。
那么如果是兩個for進行枚舉(枚舉當前修改的數字,以及后面的所有要變成的數字)是會T的,T了3發。
所以我們考慮優化這個過程。
如果當前數位改變了,如果算上當前這位數,不同的數字是< k的,那么我們就將后面的所有數字變成0。
如果 == k 那么我們就需要從前面的k個數里選最小的數進行填充。
之后判斷是否合法就好了。
用string和set寫的常數好像有點大。
#include <bits/stdc++.h> using namespace std; string n; int k; int cal(string ss) { set<char> s; for (auto c : ss) s.insert(c); return s.size(); } string solve() { cin >> n >> k; if (cal(n) <= k) return n; int len = n.size(); for (int i = len-1; i >= 0; i --) { string temp = n; ///如果當前位提高了1,那么后面的數只有取0或者取之前最小的情況 for (char j = n[i]+1; j <= '9'; ++ j) { set<char> ck; for (int l = 0; l < i; ++ l) ck.insert(n[l]); temp[i] = j; ck.insert(j); if (cal(temp.substr(0, i+1)) > k) continue; char p = cal(temp.substr(0, i+1)) < k ? '0' : *ck.begin(); for (int l = i+1; l < len; ++ l) temp[l] = p; if (stoi(temp) >= stoi(n)) return temp; } } return ""; } int main() { int t; cin >> t; while (t--) cout << solve() << '\n'; return 0; }