您的位置:首页 > 其它

HDU 4734 F(x) (数位DP,基础)

2015-10-05 10:54 309 查看
题意:

   一个非负整数的十进制位是这样的 (AnAn-1An-2 ... A2A1),定义F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1。给出A和B,问[0,B]中有几个整数x的F(x)值<=F(A)?

思路:

  算一下就知道F(x)值不会超过512*9,而B仅仅有8位十进制数,那么8*512*9就可以算出所有的统计了。对于每个询问,先计算F(A)的值,然后统计小于此值有几个就行了。统计的复杂度也是很低的。若是以前缀和来统计后面的个数的话,要么TLE,要么WA。

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define INF 0x7f3f3f3f
#define LL long long
#define ULL unsigned long long
using namespace std;
const double PI  = acos(-1.0);
const int N=10;

int f
[5120], bit
, limit;
//[第几位][上界]

int dfs(int i,int sum,bool e)
{
if(i==0)            return sum>=0;
if(sum<0)        return 0;
if(!e && ~f[i][sum] )   return f[i][sum];

int ans=0;
int u= e? bit[i]: 9;
for(int d=0; d<=u; d++)
ans+=dfs(i-1, sum-d*(1<<i-1), e&&d==u);

return e? ans: f[i][sum]=ans;
}

int cal(int n)
{
if(n<0)        return 0;
if(n==0)    return 1;

int len=0;
while(n)    //拆数
{
bit[++len]=n%10;
n/=10;
}
return dfs(len, limit, true);

}
void pre_cal(int n)
{
int len=0;
while(n)    //拆数
{
bit[++len]=n%10;
n/=10;
}
limit=0;
for(int i=1; i<=len; i++)    limit+=bit[i]*(1<<i-1);
}

int main()
{
//freopen("input.txt","r",stdin);
memset(f, -1, sizeof(f));
int t, n, Case=0;
cin>>t;
while( t-- )
{
scanf("%d%d",&limit,&n);
pre_cal(limit);
printf("Case #%d: %d\n", ++Case, cal(n));
}
return 0;
}


AC代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: