hdu4734 數字dp(減去的藝術)

2021-10-04 07:34:02 字數 1728 閱讀 8269

題目大意:求區間[l,r]內滿足數x的f(x)<=f(a)的數的個數。

對於乙個n位的數(anan-1an-2....a1),f(x)=an*2^(n-1)+an-1*2^(n-2)+...+a1*1.

題解:首先我們肯定要維護乙個狀態sum表示列舉到pos位數的前面的數字的f(x)值,最後判斷一下是否大於f(a)就行了。

因為f(x)最大為4599.所以這樣是存的下的。

但是我們還需要再開一維存預先求出來的f(a),用來記錄每一操作時對應的f(a)。

如果不用的話直接每次操作時都memset會超時。

但是這樣一來空間又不夠了,因此我們需要考慮一種狀態既不需要存f(a),memset又可以在外面執行。

這裡就體現了減去的藝術了。

定義新的狀態為dp[pos][sum]表示列舉到當前pos位,後面還需要湊sum的權值和的個數。

至於為什麼這樣是可行的呢。

我們可以這樣考慮,雖然f(a)是變的,但是每次大的f(a)總會用到小的f(a)。

而小的f(a)不會因為大的f(a)的改變而改變,因此大的sum會用到小的sum,但是小的sum不會因為f(a)的改變而改變。

**實現:

#pragma gcc optimize(2)

#include #include #include #include #include #include #include #include #include #include #include #define pi atan(1.0) * 4

#define e 2.718281828

#define rp(i, s, t) for (register int i = (s); i <= (t); i++)

#define rp(i, t, s) for (register int i = (t); i >= (s); i--)

#define ll __int64

#define ull unsigned long long

#define mst(a, b) memset(a, b, sizeof(a))

#define lson l, m, rt << 1

#define rson m + 1, r, rt << 1 | 1

#define pii pair#define mp make_pair

#define pb push_back

#define debug printf("ac\n");

using namespace std;

inline int read()

while (c >= '0' && c <= '9')

return a * b;

}int a[20];

ll dp[20][5005];

ll max;

int num;

ll dfs(int pos,int sum,int lead,int limit)

if(!limit&&!lead) return dp[pos][max-sum]=ans;

return ans;

}ll solve(ll x)

int main()

// printf("%lld\n",max);

printf("case #%d: %lld\n",++kcase,solve(b)-solve(0)+1);

}return 0;

}

HDU 4734 基礎數字dp(遞推)

以前成都賽區的題目。題意很明顯,就是有乙個f x 的函式,然後給你乙個a和b求出在0 b中有多少小於等於f a 的,預處理出來dp i j k 中有多少小於等於k的。這裡採用遞推。因為我太弱了。遞迴總是寫錯。還需慢慢加深理解。ps.很醜。還是推薦遞迴。實在不會遞推也可以。蒟蒻加油!include i...

HDU 4734 基礎數字dp(遞推)

以前成都賽區的題目。題意很明顯,就是有乙個f x 的函式,然後給你乙個a和b求出在0 b中有多少小於等於f a 的,預處理出來dp i j k 中有多少小於等於k的。這裡採用遞推。因為我太弱了。遞迴總是寫錯。還需慢慢加深理解。ps.很醜。還是推薦遞迴。實在不會遞推也可以。蒟蒻加油!include i...

HDU4734,F x (數字DP 優化)

本題思路和dp狀態不難求,比較難的是該怎麼優化。數字dp的優化可參考下面的部落格 簡單的說,一般數字dp的優化有兩種方法 將memset放置在多組資料外面,即程式每執行一次只需memset一次,這種方法要求,題目所給的約束條件是每個數本身的屬性,與輸入無關。相減,這種方法是稍微改變一下狀態,使得題目...