两个吃奶一个添下面视频_人妻第一页香蕉网_欧美xxxx少妇_妺妺窝人体色www婷婷

說(shuō)到數(shù)位DP,它主要是用于處理一些與數(shù)位有關(guān)的問(wèn)題,主要是計(jì)數(shù)問(wèn)題。并且數(shù)位DP一直以來(lái)是DP家族里比較冷門的一種,但一旦遇上了,如果不會(huì)數(shù)位DP單純靠暴力方法很難騙分。

一、什么是數(shù)位DP?

數(shù)位DP是一種計(jì)數(shù)用的DP,一般就是要統(tǒng)計(jì)一個(gè)區(qū)間[l,r]內(nèi)滿足一些條件數(shù)的個(gè)數(shù)。所謂數(shù)位DP,字面意思就是在數(shù)位上進(jìn)行DP。數(shù)位還算是比較好聽(tīng)的名字,數(shù)位的含義:一個(gè)數(shù)有個(gè)位、十位、百位、千位......數(shù)的每一位就是數(shù)位!

之所以要引入數(shù)位的概念完全就是為了DP。數(shù)位DP的實(shí)質(zhì)就是換一種暴力枚舉的方式,使得新的枚舉方式滿足DP的性質(zhì),然后記憶化就可以了。

數(shù)位DP往往都是這樣的題型,給定一個(gè)閉區(qū)間[l,r],讓你求這個(gè)區(qū)間中滿足某種條件的數(shù)的總數(shù)。而這個(gè)區(qū)間可能很大,簡(jiǎn)單的暴力代碼如下:

int ans=0;
for(int i=l;i<=r;i++){
    if(check(i))ans++;
}

我們發(fā)現(xiàn),若區(qū)間長(zhǎng)度超過(guò)1e8,我們暴力枚舉就會(huì)超時(shí)了,而數(shù)位DP則可以解決這樣的題型。數(shù)位DP實(shí)際上就是在數(shù)位上進(jìn)行DP。

數(shù)位DP解法

數(shù)位DP就是換一種暴力枚舉的方式,使得新的枚舉方式符合DP的性質(zhì),然后預(yù)處理好即可。

 我們來(lái)看:我們可以用f(n)表示[0,n]的所有滿足條件的個(gè)數(shù),那么對(duì)于[l,r]我們就可以用[l,r]?f(r)?f(l?1),相當(dāng)于前綴和思想。那么也就是說(shuō)我們只要求出f(n)即可。那么數(shù)位DP關(guān)鍵的思想就是從樹的角度來(lái)考慮。將數(shù)拆分成位,從高位到低位開始枚舉。我們可以視N為n位數(shù),那么我們拆分數(shù)位DP解法。那么我們就可以開始分解建樹,如下。之后我們就可以預(yù)處理再求解f(n)了,個(gè)人認(rèn)為求解f(n)是最難的一步。

數(shù)位DP解法內(nèi)容

聽(tīng)完是不是有點(diǎn)繞,我們可以來(lái)點(diǎn)題目練習(xí)一下,做完就會(huì)發(fā)現(xiàn)了數(shù)位DP的套路了。


二、數(shù)位DP經(jīng)典例題

例題:度的數(shù)量

題目:求給定區(qū)間 [X,Y] 中滿足下列條件的整數(shù)個(gè)數(shù):這個(gè)數(shù)恰好等于K個(gè)互不相等的B的整數(shù)次冪之和。例如,設(shè) X=15,Y=20,K=2,B=2,則有且僅有下列三個(gè)數(shù)滿足題意:

度的數(shù)量

輸入格式

第一行包含兩個(gè)整數(shù) X 和 Y,接下來(lái)兩行包含整數(shù) K 和 B 。

輸出格式

只包含一個(gè)整數(shù),表示滿足條件的數(shù)的個(gè)數(shù)。

數(shù)據(jù)范圍

數(shù)據(jù)范圍

輸入樣例:

15 20

2

2

輸出樣例:

3

解題思路

此題實(shí)際上就是將十進(jìn)制數(shù)轉(zhuǎn)化為B進(jìn)制數(shù),判斷位數(shù)上的值是否為1。那么我們可以視N為n位數(shù),那么我們拆分數(shù)位DP。從樹的角度考慮:我們?cè)O(shè)N=76543210,B=10,那么我們從高位往最低位開始枚舉如下;枚舉an時(shí),我們有兩種選擇:

(1)走右邊分支,那么我們填例子,而題目要求每一位只能填1或者0,而an>1,所以不是合法方案,我們直接剔除。

(2)走左邊分支,那么我們可以填0~6,即走左邊分支,那么由于每一位只能填1或者0,所以我們累加這兩種選擇的方案。

記住,走到了左邊分支是可以直接累加的。

所以我們實(shí)際上還是要做一個(gè)預(yù)處理的,我們用f[i][j]表示還剩下i位沒(méi)有填,且需要填寫j個(gè)1的方案數(shù)。那么在(i,j)這個(gè)狀態(tài),我們可以選擇填1,那么接下來(lái)的狀態(tài)就是f[i?1][j?1],而如果填0,那么接下來(lái)的狀態(tài)就是f[i?1][j],那么狀態(tài)轉(zhuǎn)移方程就是f[i][j]=f[i-1][j]+f[i][j?1]。而初始狀態(tài)即是當(dāng)j=0時(shí),f[i][0]=1。這樣我們就可以預(yù)處理f數(shù)組了。

處理完之后我們就可以直接模擬做了。

代碼如下:

/**
  *@filename:度的數(shù)量
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-05-12 11:23
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;

int l,r,k,b;
int f[35][35];
//首先我們先預(yù)處理f數(shù)組。其中f[i][j]表示剩下還有i個(gè)沒(méi)填,需要填寫j個(gè)1的方案數(shù)。
void init(){
    for(int i=0;i<35;i++){
        for(int j=0;j<=i;j++){
            if(!j)f[i][j]=1;
            else{
                f[i][j]=f[i-1][j]+f[i-1][j-1];
            }
        }
    }
}
int dp(int n){
    //求解f(n)。我們需要避免n為0的情況,這里需要特判。
    if(!n)return 0;
    vector<int> nums;//將n分割,存儲(chǔ)位數(shù)。
    while(n){
        nums.push_back(n%b);
        n/=b;
    }
    int ans=0;//答案。
    int last=0;//前面的信息,這里代表的是前面分支選取了多少個(gè)1.
    for(int i=nums.size()-1;i>=0;i--){
        int x=nums[i];
        if(x){
            //說(shuō)明x>0,我們可以選擇左邊分支填0.
            ans+=f[i][k-last];
            if(x>1){
                //當(dāng)x>1我們才可以枚舉左邊分支填1.
                if(k-last-1>=0){
                    //如果還可以填1的話。
                    ans+=f[i][k-last-1];
                }
                break;//因?yàn)橛疫叿种е荒転?或1,所以不符合條件。break。
            }
            else{
                //當(dāng)x=1就可以進(jìn)入右邊的分支繼續(xù)討論。
                last++;
                if(last>k)break;
            }
        }
        //考慮到最后一位,如果符合條件那么末位填0也算一種方案。
        if(!i&&last==k)ans++;
    }
    return ans;
}
void solve(){
}
int main(){
    cin>>l>>r>>k>>b;
    init();
    cout<<dp(r)-dp(l-1)<<endl;
    solve();
    return 0;
}


點(diǎn)贊(0)

C語(yǔ)言網(wǎng)提供由在職研發(fā)工程師或ACM藍(lán)橋杯競(jìng)賽優(yōu)秀選手錄制的視頻教程,并配有習(xí)題和答疑,點(diǎn)擊了解:

一點(diǎn)編程也不會(huì)寫的:零基礎(chǔ)C語(yǔ)言學(xué)練課程

解決困擾你多年的C語(yǔ)言疑難雜癥特性的C語(yǔ)言進(jìn)階課程

從零到寫出一個(gè)爬蟲的Python編程課程

只會(huì)語(yǔ)法寫不出代碼?手把手帶你寫100個(gè)編程真題的編程百練課程

信息學(xué)奧賽或C++選手的 必學(xué)C++課程

藍(lán)橋杯ACM、信息學(xué)奧賽的必學(xué)課程:算法競(jìng)賽課入門課程

手把手講解近五年真題的藍(lán)橋杯輔導(dǎo)課程

Dotcpp在線編譯      (登錄可減少運(yùn)行等待時(shí)間)