您的位置:首页 > 其它

HDU 4734 F(x) (数位dp)

2017-08-31 09:11 465 查看
http://acm.hdu.edu.cn/showproblem.php?pid=4734

题意:

给了个f(x)的定义:F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1,Ai是十进制数位,然后给出a,b求区间[0,b]内满足f(i)<=f(a)的i的个数。

思路:

dp[pos][sum]表示分析到第pos位上值还剩sum的个数,一开始sum设为f(a),之后不断减就可以了。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=100000+5;

int a,r;
int tot;
int ans;
int dp[20][2*maxn];
int dig[30];

int f(int x)
{
if(x==0) return 0;
int ans=f(x/10);
return ans*2+(x%10);
}

int dfs(int pos, int sum, bool limit)
{
if(pos==-1) return sum>=0;
if(sum<0)  return 0;
if(!limit && dp[pos][sum]!=-1)  return dp[pos][sum];
int ans=0;
int up=limit?dig[pos]:9;
for(int i=0;i<=up;i++)
{
ans+=dfs(pos-1,sum-i*(1<<pos),limit && i==dig[pos]);
}
if(!limit)  dp[pos][sum]=ans;
return ans;
}

int solve(int x)
{
int pos=0;
while(x)
{
dig[pos++]=x%10;
x/=10;
}
return dfs(pos-1,tot,1);
}

int main()
{
//freopen("in.txt","r",stdin);
int T;
int kase=0;
scanf("%d",&T);memset(dp,-1,sizeof(dp));
while(T--)
{

scanf("%d%d",&a,&r);
tot=f(a);
printf("Case #%d: %d\n",++kase,solve(r));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: