日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(待完成)qbxt2019.05 总结2 - 数位DP

發(fā)布時間:2023/12/9 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (待完成)qbxt2019.05 总结2 - 数位DP 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

數(shù)位 DP 嚴格來說其實并不是 DP……它只是個單純的計數(shù)問題

但是怎么說呢……現(xiàn)在大家似乎都把數(shù)位 DP 叫這個名字,所以……我們還是……叫它 DP

額什么是數(shù)位 DP 呢?

一句話概括——一類求在 K 進制下m滿足條件的數(shù)的數(shù)量有多少個的算法

常見的問題形式:

求 [l..r] 之間的在 K 進制下滿足條件 F 的數(shù)有多少個?

什么?你說for (int i = l ; i <= r; i++) ans+=check(i);?

別學競賽了,回家養(yǎng)鯤吧

我們很快就會發(fā)現(xiàn),數(shù)位 DP 的復雜度和位數(shù)相關,所以一般數(shù)據(jù)規(guī)模奇大

(以上摘自lyd課件)

數(shù)位DP

(以下基于k進制討論)

數(shù)位DP一般會讓你求\([l,r]\)滿足條件的個數(shù),這里我們設函數(shù)\(c(x)\)表示小于x的正整數(shù)中滿足條件的個數(shù),則最終答案就是 \(c(r+1)-c(l)\) 。但k進制時加一操作不一定好實現(xiàn),所以更常用的是 \(c(r)-c(l)+\text{對r的特判結果}\)

所以問題轉化為求\(c(x)\)

正如它名字中的“數(shù)位”,DP狀態(tài)的第一維通常是數(shù)字的位數(shù)。所以只要寫出轉移方程,就可以得到小于\(k^x\)的滿足條件的個數(shù)(其中x是任意/給定正整數(shù))即\(\sum dp[x][...]\)

現(xiàn)在要求\(c(x)\)。設\(x\)\(l\)位,且現(xiàn)在已經(jīng)求得了\(dp[l-1][...]\)。現(xiàn)在考慮最高位,分為兩種不同的情況:

  • 滿足條件的y的最高位小于x的最高位。這時能保證\(y<x\),所以后面任意選。

  • 滿足條件的y的最高位等于x的最高位。這時可以遞歸解決后面的位構成的子問題。但我們發(fā)現(xiàn)遞歸完全是浪費,因為子問題求出的dp數(shù)組是一樣的。所以在子問題中真正有用的是求情況1和遞歸下一層。

    因為遞歸的層數(shù)是遞減的,于是我們可以把遞歸改為循環(huán)。


  • 上面這些抽象的描述說實話我都看不懂QAQ

    考慮這樣的一道題目:求\([l,r]\)中不包含4和62的數(shù)的個數(shù)。

    那么就可以設\(c(x)\)為小于\(x\)的數(shù)中不包含4和62的數(shù)的個數(shù),最終答案即為\(c(r+1)-c(l)\)

    這里可以設\(dp[i][j]\)表示長度為i位的,最高位是j的滿足條件的數(shù)的個數(shù)。然后我們可以寫出這樣的轉移方程:\(dp[i][j](j\neq4)=sum\{dp[i-1][k]|\text{當}j=6\text{時}k\neq2\}\)

    下面假設x有l(wèi)位,最高位是x[1],最低位是x[l],其他類似。這一段代碼求出了dp數(shù)組。

    for(int j=0;j<=9;j++){if(j==4)continue;dp[1][j]=1; } for(int i=2;i<=l;i++){for(int j=0;j<=9;j++){if(j==4)continue;for(int k=0;k<=9;k++){if(j==6&&k==2)continue;dp[i][j]+=dp[i-1][k];}} }

    然后考慮情況一。

    int ans=0; for(int j=0;j<x[1];j++){if(j==4)continue;ans+=dp[l][j]; }

    然后是情況二。先寫遞歸版。(toint表示將數(shù)組表示的數(shù)字轉換成int,toarr則相反)

    ans+=c(從前面去掉1位的x);

    這時我們可以發(fā)現(xiàn),在第一次遞歸里有用的代碼是如下的部分:

    for(int j=0;j<x[2];j++){if(j==4||(j==2&&x[1]==6)continue;ans+=dp[2][j]; } ans+=c(從前面去掉2位的x);

    所以最終我們應該把代碼修改為這樣子:

    int ans=0; for(int i=l;i>=1;i--){for(int j=0;j<x[l-i+1];j++){if(j==4||(j==2&&x[l-i]==6))continue;ans+=dp[i][j];} }

    轉載于:https://www.cnblogs.com/water-lift/p/10809884.html

    總結

    以上是生活随笔為你收集整理的(待完成)qbxt2019.05 总结2 - 数位DP的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。