给定一个数字,计算出0-n以内所有数字在二进制状态下“11”的个数。
范围是int那么大,dp的话差不多就是数位dp...
dp[site][last][cnt]代表当前二进制有site位,上一位的状态为last,已经有cnt个11了..
最开始尝试用dp[site][last]去解,发现总会少计算...是因为记忆化搜索的时候dp数组不够表示那么多的状态...
这个题感觉直接递推式也是可以做的..
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[35][2][35];
int num[35];
ll dfs(int site,int last,int cnt,int f)
{
if(site==0) return cnt;
if(!f&&dp[site][last][cnt]!=-1)
return dp[site][last][cnt];
ll ans=0;
int len=f?num[site]:1;
for(int i=0;i<=len;i++)
{
if(i==1&&last==1)
ans+=dfs(site-1,i,cnt+1,f&&i==len);
else
ans+=dfs(site-1,i,cnt,f&&i==len);
}
if(!f)
dp[site][last][cnt]=ans;
return ans;
}
ll solve(int n)
{
int i=1;
while(n)
{
num[i++]=n%2;
n=n/2;
}
return dfs(i-1,0,0,1);
}
int main()
{
int t,n;
memset(dp,-1,sizeof(dp));
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
scanf("%d",&n);
printf("Case %d: %lld\n",cas,solve(n));
}
return 0;
}