小學生都能看懂的數字dp

2022-05-20 20:17:14 字數 3123 閱讀 5018

數字\(dp\)歸為計數\(dp\),通常需要統計乙個區間\([l,r]\)內滿足某些限制條件的個數

數字dp其實很久前就知道了,也做過幾道和其他演算法混在一起的題目,其實通過手玩是能做的

但畢竟是種演算法,還是系統學下比較好(節省手玩時間)

p2602 [zjoi2010]數字計數

求\([l,r]\)間,\(0\)到\(9\)在數字上出現的次數

設陣列\(dp_i\)為滿\(i\)位每個數字出現的次數,也是說四位我們都算進去而忽略前導0的存在

而實際中顯然像0012這樣的數字我們是不會統計那兩個0的

(滿位情況下每個數字出現次數相同故我們可以公用空間)

則\(dp_i=dp_+10^\),理解??

比如從一位到兩位:

\(1.\)

\(0\)

$9$在第一位各出現一次,到兩位時它們前面補上$0$

\(9\)(第一位為0:00,10......90)故在\(dp_\)基礎上乘\(10\)

\(2.\)不僅要算原有位出現的次數,新加的該位也要算(第二位為1:10,11......19),數滿\(i-1\)位,故加上\(10^\)

當然你也可以手玩一遍驗證一下

#includeusing namespace std;

typedef long long ll;

ll dp[20],tmp[20],a[20];

int main()

for(ll i=0;i<=9999;++i)

for(ll j=1,bit=i;j<=4;++j)

++a[bit%10],

bit/=10;

printf("%lld",dp[4]);printf("\n");

for(ll i=0;i<=9;++i)

printf("%lld ",a[i]);printf("\n");

return 0;

}

現在來考慮前導\(0\),第\(i\)位為前導\(0\)時,實際上我們多算了填滿\(i-1\)位的次數,減去就好

my complete code(**有少量注釋,應該容易看懂)

#include#include#include#include#includeusing namespace std;

typedef long long ll;

inline ll read()

while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();

return x*f;

}ll l,r;

ll a[20],cover[20],dp[20],countl[20],countr[20];

inline void solve(ll num,ll *a)

for(ll i=len;i>=1;--i)\)表示前\(i\)位,第\(i\)位為\(j\)的方案數\((\)稍微做過點動規的人這個都不成問題吧\()\)

考慮\(solve(x)\)為求\(x\)以內的答案

分三部分做\((\)設\(len\)為數字,每一位為\(a_i)\)

但我們發現其實是在計算\(x-1\)以內的答案\((\)第三部分使得最低位統計不到上界\()\)

#includeusing namespace std;

typedef long long ll;

ll l,r;

ll dp[15][10],a[15];

inline void calc()

inline ll solve(ll x)

for(ll i=1;i用記憶化搜尋來做,拋開迴圈後轉移狀態能更加隨意,大部分數字動規的題都可隨意切

拿上題舉例,我們用\(dfs(now,num,top)\)表示遍歷到第\(now\)位,上一位為\(num\),是否頂著上界

每層確定這一位選啥,判斷是否和上一位衝突,全部確定完了方案數\(+1\)

#includetypedef long long ll;

ll l,r;

ll f[11][10],a[11],dp[11][10];

inline void calc()

ll dfs(ll now,ll num,ll top)

inline ll solve(ll num)

ll ret(0);

for(ll i=1;i<=a[tot];++i) ret+=dfs(tot-1,i,i==a[tot]);

for(ll i=tot-1;i>=1;--i)

for(ll j=1;j<=9;++j)

ret+=dp[i][j];

return ret;

}int main()

搜尋的方法相比純迴圈計算,由於上道題限制較少難度簡單,故顯得有點雞肋

[cqoi2016]手機號碼

11位的手機號,在\([l,r]\)求出滿足兩個條件的方案數:至少有三位連續的數字相同,不能同時出現\(4\)和\(8\),

\(dfs(now,p,pp,\_4,\_8,top,hw)\)

分別表示到第幾位了,前一位數字,前兩位數字,是否出現過\(4/8\),是否頂著上界,是否出現過了三連

用冗長的七重迴圈直接番了五倍的**量

#includeusing namespace std;

typedef long long ll;

ll l,r;

ll f[12][10][10][2][2][2],a[20];

ll dfs(ll now,ll p,ll pp,ll _4,ll _8,ll top,ll hw)

inline ll solve(ll x)

if(tot!=11) return 0;

ll ret(0);

for(ll i=1;i<=a[tot];++i)

ret+=dfs(tot-1,i,0,(i==4),(i==8),i==a[tot],0);

return ret;

}int main()

inline ll solve(ll x)

dfs(....);

return ret;

}

新手都能看懂的Dubbo!

1.dubbo架構 上述節點簡單說明 呼叫關係說明 1.服務容器負責啟動,載入,執行服務提供者。2.服務提供者在啟動時,向註冊中心註冊自己提供的服務。3.服務消費者在啟動時,向註冊中心訂閱自己所需的服務。4.註冊中心返回服務提供者位址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者...

小白都能看懂的block

首先說明一下,我自己也是乙個小白 這是我對block的一點認識或總結,有不對的地方,希望大家指出來 block就是乙個 塊,用來執行一小段程式的,通常我們定義乙個block 可以用它的基本模型,返回值型別 變數的名字 引數型別 例如 int myblock int 這就是定義了乙個block 這個變...

小白都能看懂的softmax詳解

softmax把一些輸入對映為0 1之間的實數,並且歸一化保證和為1,因此多分類的概率之和也剛好為1 或參考 小白都能看懂的softmax詳解 在機器學習尤其是深度學習中,softmax是個非常常用而且比較重要的函式,尤其在多分類的場景中使用廣泛。他把一些輸入對映為0 1之間的實數,並且歸一化保證和...