數位dp的思想在於:對於例如725這個數,我們計算1-725或者0-725之間的所有情況。
從最高爲開始:有0,1,2,3,4,5,6,7.
其中:兩個數字最爲關鍵:0,7,而其他數字則是包含了以後所有的情況。
故我們需要對這兩個數字採用兩個bool類型來判定。
一共就有四種情況。
性質:
1.數位dp中,經常關注每個數位上的值,這就導致在很多情況下,由於數位的增長非常容易的原因,導致滿足符合條件的情況很多,因此對於滿足條件的情況增長也是非常快的。
HDU - 6644 這個題的關鍵點就是發現數位的增長非常快,我們可以簡化dp的複雜度。
dp[i][j]記錄第i位模爲j的個數
數位dp模板:
struct Num
{
int dig[100];
int len;
int rad;
Num(){len=0;}
void read(int x,int radix)
{
rad=radix;
len=0;
while(x)
{
len++;
dig[len]=x%rad;
x=x/rad;
}
}
void trans(int radix)
{
int num=0;
for(int i=len;i>=1;i--)
num=num*rad+dig[i];
read(num,radix);
}
};
struct Digdp
{
ll a[40][20]; // 數位,數值,其他
Num num;
Digdp(){memset(a,-1,sizeof(a));}
ll read(Num x)
{
num=x;
ll ans=0;
int maxNum=num.dig[num.len];
for(int i=0;i<maxNum;i++)
ans=ans+dfs(num.len,i,0);
ans=ans+dfs(num.len,maxNum,1);
return ans;
}
ll dfs(int pos,int val,bool limit)
{
if(limit==0)
{
if(a[pos][val]!=-1)
return a[pos][val];
/*handle*/
}
/*handle*/
}
};
具體細節部分如下:
struct Num
{
int dig[100],len,rad;
Num(){len=0;}
void read(int x,int radix)
{
rad=radix;len=0;
while(x)
{
len++;
dig[len]=x%rad;
x=x/rad;
}
}
void trans(int radix)
{
int num=0;
for(int i=len;i>=1;i--)num=num*rad+dig[i];
read(num,radix);
}
};
struct Digdp
{
ll a[40][20]; // 數位,數值,其他
Num num;
Digdp(){memset(a,-1,sizeof(a));}
ll read(Num x)
{
num=x;
ll ans=0;
int maxNum=num.dig[num.len];
for(int i=0;i<maxNum;i++)ans=ans+dfs(num.len,i,0,1);
ans=ans+dfs(num.len,maxNum,1,0);
return ans;
}
ll dfs(int pos,int val,bool limit,bool isz)
{
if(pos==0)return 0;
if(limit==0)//用來判定當前是否被限制了!對於全0的情況,肯定包含在沒有被限制之中
{ //由於沒有被限制,需要存儲dp結果。
if(a[pos][val]!=-1)return a[pos][val];
a[pos][val]=0; //對於全0,和非全0 運算步驟上沒有區別,只是條件分支不一樣
for(int i=1;i<num.rad;i++)a[pos][val]=a[pos][val]+dfs(pos-1,i,0,0); //其他數字
if(isz==1)a[pos][val]=a[pos][val]+dfs(pos-1,0,0,1); //當前全0,後面是0 ,依然沒限制,全0
else a[pos][val]=a[pos][val]+dfs(pos-1,0,0,0); //當前非全0,後面是0 ,依然沒限制,非0
return a[pos][val];
}
else
{ //三部分組成 0 1-num-1 num
ll ans=0;
int dig=num.dig[pos-1];
ans=ans+dfs(pos-1,dig,1,0); //計算被限制部分
if(dig!=0) //被限制部分非0,計算其他部分
{
ans=ans+dfs(pos-1,0,0,0);
for(int i=1;i<dig;i++)ans=ans+dfs(pos-1,i,0,0);
}
return ans;
}
}
};