補充點在其他題解裏面沒有的其他東西。
首先是之所以可以數位dp並且不會算錯的原因是,對於每一個數字,如果這個數字是槓桿數,那麼他的支點有且只有一個,如果一個數字有多個支點,那麼數位dp去枚舉支點就會算重複,算多。
另外全部人都是在說數位dp然後枚舉支點,對R和L-1分別做一次dp,但是可以有個小優化就是,我們要明確一個東西,dp數組存的是那些沒有被限制的的有用數字是數量,也就是對於任意數都適用。
那麼我們可以發現在枚舉支點位置的時候,枚舉位置1,對於R和L-1都分別去dfs了一次,但是實際上所做的效果是一樣的,因爲對於沒有被限制的數字他的數量是不會變的,所以我們可以把兩個數字一起來算,每一次枚舉支點都可以一次性統計。
int solve(int x,int y) {//L, R
memset(dp, -127, sizeof(dp));
int pos1 = 0,pos2 = 0;
while (x) {
num[1][pos1++] = x % 10;
x /= 10;
}
while (y) {
num[2][pos2++] = y % 10;
y /= 10;
}
int ans1 = 0,ans2 = 0;
for (int i = 0; i < 17; i++) {
ans2 += dfs(pos2 - 1, true, 0, i, 0, 2);
ans1 += dfs(pos1 - 1, true, 0, i, 0, 1);
}
return ans2 - ans1;
}
這是我是solve函數,枚舉所有的支點位置,然後一起統計就可以了,這樣就可以充分的利用之前跑出一遍所獲得的貢獻,在一個另外的點就是,你還可以在開一個維度,那個維度代表的就是你現在枚舉的是哪個支點,就是空間換時間,你就可以不用每次枚舉支點的時候都來一次memset。