POJ 3252 區間內一個數的二進位制中0的數量要不能少於1的數量(數位DP)
阿新 • • 發佈:2018-11-06
題意:求區間內二進位制中0的數量要不能少於1的數量
分析:很明顯的是數位DP;
菜鳥me : 整體上是和數位dp模板差不多的 , 需要注意的是這裡有前導零的影響 , 所以需要在dfs()裡面增加zor 變數的限制條件 ,
那麼我們的dp[i][j] 是表示第i 位置 , ,0的數量減去1的數量不少於 j 的方案數 , 那剩下的就簡單了咯 ,哦還需要注意的是 這裡的 j 會出現負數的情況 , 那也很好解決咯 ,偏移下就好拉 , 從32開始 ,也就是說32表示0
#include<stdio.h>
#include <string.h>
int dp[40][70];
int a[70];
int dfs(int pos , int sta , int limit , int zor)
{
if(pos==-1)
return sta>=32;
if(!limit && !zor && dp[pos][sta]!=-1)
return dp[pos][sta];
int up=limit?a[pos]:1;
int ans=0;
for(int i=0 ; i<=up ; i++)
{
if(zor && i==0)
ans+=dfs(pos-1,sta,limit&&i==a[pos],zor&&i==0);
else
{
if(i==0)
ans+=dfs(pos-1,sta+1,limit&&i==a[pos],zor&&i==0);
else
ans+=dfs(pos-1,sta-1,limit&&i==a[pos],zor&&i==0 );
}
}
if(!limit && !zor)
dp[pos][sta]=ans;
return ans;
}
int so(int x)
{
int ans=0;
while(x)
{
a[ans++]=x%2;
x/=2;
}
return dfs(ans-1,32,1,1);
}
int main( )
{
int l,r;
memset(dp,-1,sizeof(dp));
while(scanf("%d%d",&l,&r)!=EOF)
{
printf("%d\n",so(r)-so(l-1));
}
return 0;
}
View Code