動態規劃專題 解題報告 M

2021-09-23 14:00:12 字數 2655 閱讀 9124

別的我不說了,良心題解先吹一波好吧。

最重要的使這一段

假如第一位4,第二位7,三四位就可以隨便取了。設這種狀態為(2,2),意思為前兩位已經匹配上了4750的第二位。則用dp[2][2]表示(dp[100010][5],一共5*1e5種狀態)。

那麼(2,2)就有10種選擇(0~9):

·會轉移1次到(3,3)(選5);

·1次(3,1)(選4);

·8次(3,0)(選其他)

在一番推導後,能得到狀態轉移方程如下:

for (int i = 0; i <= upp; i++)			//從0到當位可以取到的最大值

整個dfs函式思路如下:

void dfs()
我的寫法:

int dfs(int pos, int now, int lim, char *s, int pre, int num,int len)

//當前位置,當前匹配的多少位置,對於取位的限制,當前字串,然後是一些提前預處理過的陣列,最後是當前串的長度

if (!lim)

dp[pos][now1] = ret % zh; //最後有乙個更新記憶化的操作,然後return

return ret % zh;

}

if(!lim)								

ret = ret * pre[pos] % zh;

else

ret = ret * (num[pos] + 1) % zh;

因為限制的不同,在取到4位的情況下,

如果不被限制,那麼後面所有位數取0到9都行,那麼就是乙個10的次方倍數的個數可以被累加進ret,這就是當前位置的pre陣列儲存的數字。

如果被限制了,則只能取到當前位後面的數字+1個,比如題解中475027,已經有了4750,那麼可以選0到27有28種選擇,每一位都提前計算並儲存在num裡。

這裡重點講一下這個限制 limit,算是數字dp的最精髓操作,也是最難的一部分(其實現在看來思路也滿清晰的),其實就是下一位能不能亂取0~9,先想想什麼時候不能,就是當前面所有的值都取到了最高位,你有乙個數字4751,前面都去了475了,剩下就只有0和1,但是如果前面取的474,那麼0到9都可以隨便選,都不會超過4751。

所以我們可以發現:

若當前位 limit = 1, 而且已經取到了能取到的最高位時,下一位 limit = 1;

若當前位 limit = 1, 但是沒有取到能取到的最高位時,下一位 limit = 0 ;

若當前位 limit = 0時,下一位 limit = 0 。

那麼總結出下一位的limit的狀態:lim && upp==i

最後按著思路寫就能ac

#include#define for(a, b, c) for(int a=b; a<=c; a++)

#define maxn 100005

#define maxm 55

#define hrdg 1000000007

#define zh 16711680

#define inf 2147483647

#define llinf 9223372036854775807

#define ll long long

#define pi acos(-1.0)

#define ls p<<1

#define rs p<<1|1

#define int long long

using namespace std;

char l[maxn], r[maxn];

int lenl, lenr;

int ans1, ans2, ans, dp[maxn][5];

int numl[maxn], numr[maxn], prel[maxn], prer[maxn];

int key[5] = ;

int qpow(int a, int x)

return ret % zh;

}void init()

for (int i = lenr; i >= 1; i--)

}int dfs(int pos, int now, int lim, char *s, int pre, int num,int len)

else

int upp = lim ? s[pos]-'0' : 9;

for (int i = 0; i <= upp; i++)

if (!lim)

dp[pos][now1] = ret % zh;

//printf("lim = %d pos = %d now = %d ret = %d\n", lim, pos, now1, ret);

return ret % zh;

}signed main()

//printf("ans1 = %lld ans2 = %lld\n", ans1, ans2);

ans = ((ans % zh + ans2) % zh - ans1 + zh) % zh;

cout << ans;

return 0;

}

動態規劃專題 解題報告 A

乙個經典的貨郎擔問題,加上17的範圍限制各種明示狀態壓縮,用二進位制來表示走過哪幾個城市,我們可以開乙個二維陣列dp i j 表示走過了i的城市,最後在j城市停留的距離。預處理一遍每個城市間的距離,算出dis i j 到dp i j 的狀態可以由 1 1 j k 轉移過來,比較距離儲存最優值就行,然...

動態規劃專題 解題報告 D

我們先來想想n2 怎麼做,兩個n2 迴圈乙個求以i結尾的最長上公升子串行,另乙個逆序求一遍,然後列舉i,以i為中間點的長度,迴圈更新結果就有了。是不是很簡單,恭喜你tle。想都不用想必t好嗎?沒有個nlogn演算法怎麼在1e6的資料範圍面前找場子?nlo gn nlogn nlog n做法 我們其實...

動態規劃專題 解題報告 B

首先在從乙個點,目標是向西運輸,那麼它一路走過的路徑x中可能朝西也可能朝北,但最終指向的都是西邊,畫圖可知西方同行中所有的礦點必只能向西運輸,即使是從出發就開始一路向北,最終也只能匯流進路徑x中,指向西。從該點向北的運輸,北方同列的考慮也是一樣的。我們可以預處理出從乙個點向西和向北的貢獻是什麼。我們...