數字DP做題記錄

2021-09-20 12:52:46 字數 1523 閱讀 7048

xdu1161(一本通1588)

思路:用二維陣列dp[i][j]表示數字取到i位的情況下,各位數字之和對題中所給n取模為j的數字個數。例如對於樣例來說,dp[1][0]表示數字最多可取到1位,各個位之和對9取模為0個數字個數,這樣的數字有兩個,即0和9。

類似地,dp[1][1]=1,因為1%9=1;dp[1][2]=1,因為2%9=2;dp[2][0]=11,因為0,9,18,27,36,45,54,63,72,81,90,99滿足條件。注意這裡dp數字的dp[i][j],i是指數字的總位數可以是1,2,.....i,而不是只算位數是i的數字。

可以先預處理一下dp陣列,假如模數為mod,先用乙個for迴圈賦值dp[1][0]到dp[1][mod-1]

for(int i=0;i<=9;i++) dp[1][i%mod]+=1;

然後用i可以遞推i+1的情況,如果已經知道dp[i][j]的值,現在將數字位數可取值增加到i+1,第i+1位上的數字可以取0到9,假如取的是y,由於之前i位之和取模後是j,加上這個y之後,總共的i+1位之和取模後應該是(j+y)%mod,所以dp[i+1][(j+y)%mod]+=dp[i][j]。

求取區間[a,b]之間符合條件的數字個數,可以當作求0到b之間符合的個數減去0到a-1之間符合條件的個數。

要求0到x中間符合條件的數字個數,先把x每一位存到陣列shu[13]中,例如x=387,求0到387之間,對9取模符合要求的個數。

387被儲存為 shu[1]=7,shu[2]=8,shu[3]=3;(這個順序和數字讀起來剛好相反了)。

假如要暴力列舉的算,可以發現,當數字的最高位取其最大值時,低位的取值是受限制的,最高位取2時,十位上最多只能取到8,但如果最高位取1或者2,後兩位是任意取0到9之間。所以,對於最高位取值val所以最高位取1,或者2時,對答案貢獻 dp[1][8]和dp[2][7]。

最高位取0時,低的兩位也都是可以取0到9之間任意值的,這時對答案貢獻dp[2][0],

最高位取3時,就開始出現限制,這時第二位只能取0到8。而取8時最低位也受到限制只能取0到7。這裡再分一次情況:

第二位取0到7時,最低為可以任意取0到0,並且由於最高位對mod取模為3,其餘各位之和需要對mod取模為6,所以第二位取0到7時,對答案貢獻為dp[1][6],dp[1][5],dp[1][4],dp[1][3],dp[1][2],dp[1][1],dp[1][0],dp[1][8]。

第二位取8時,最低位可以取0到7,對於取到最低位的情況,可以直接把各個位置之和加起來,取模為0則答案加1。

#include #define ll long long

using namespace std;

ll n,m,mod;

ll shu[13];

ll dp[13][110];

int cnt;

void init()

}he+=shu[i];

}if(he%mod==0)ans++;

return ans;

}int main()

return 0;

}

毒瘤 dp 題做題記錄

題目鏈結 設 f 表示以 i 結尾的一組選擇了 j 個數,剩下的也能湊出一組時,剩下一組結尾數的最小值。當 a a i 時,i 與 i 1 可以分到一組,因此 f max f f 當 a f 時,i 1 能分到剩下的一組,該組原有 j i 個數,因此 f max f a i include incl...

KMP做題記錄

題目太長不貼了 這道題很巧妙,給定乙個字串s,求最少在首尾新增幾個字元後,s變為乙個迴圈了n次的字串 n 1 假設我們有乙個迴圈串s abcabcabc 我們根據kmp求一次next陣列,就可以通過next strlen s 得到乙個迴圈節的位置從而求出迴圈節的長度,顯然,迴圈節能被s整除。如果s ...

8 25 9 25 做題記錄

2018.8.25 上午 1.ac 洛谷p1514引水入城 搜尋 貪心 2.ac 洛谷p3918 國家集訓隊 特技飛行 貪心 下午 3.ac 洛谷p1120 小木棍 資料加強版 搜尋 剪枝 4.ac 洛谷p1441 砝碼稱重 dfs列舉 01揹包 2018.8.26 上午 參加模擬賽 下午 1.ac...