HDU 4734 F(x) 【DP】

点我打开题目原文!!!

题意:

定义F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 1   ,给定A,B,求0-B范围内X使得F(X)<=F(A).

解题思路:

这题不难,dp[i][is][Max]表示从第i位开始,is表示是否为边缘情况,Max表示F值<=Max。枚举第i位,记忆化搜索转移就可以了。这题TLE了好几发,原因是把边缘条件和非边缘条件一起记忆化了,导致每次初始化花了很多时间,其实非边缘情况与具体数据无关,只用初始化一次。这题测试组数非常多,不知道为什么能这么快过,按理说复杂挺高的!

代码:

<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<map>
#include<string>
#include<queue>
#include<vector>
#include<list>
#include<bitset>
//#pragma comment(linker,"/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
int A,B;
int dig[10];
int dp[10][2][5000];
int fac[20];
int f(int n)
{
    int ret=0;
    int b=1;
    while(n)
    {
        int r=n%10;
        ret+=r*b;
        b*=2;
        n/=10;
    }
    return ret;
}
int dfs(int p,int is,int Max)
{
    if(p==-1) return Max>=0;
    if(dp[p][is][Max]!=-1&&!is) return dp[p][is][Max];
    int up=is?dig[p]:9;
    int ret=0;
    for(int i=0;i<=up;i++)
    {
        int r=i*fac[p];
        if(r<=Max) ret+=dfs(p-1,is&&i==up,Max-r);
    }
    return dp[p][is][Max]=ret;
}
int get()
{
    int n=B;
    int len=0,ret=0;
    while(n)
    {
        dig[len++]=n%10;
        n/=10;
    }
    ret=dfs(len-1,1,f(A));
    return ret;
}
int main()
{
    fac[0]=1;
    for(int i=1;i<20;i++) fac[i]=fac[i-1]*2;
    int t,tt=0;
    scanf("%d",&t);
    memset(dp,-1,sizeof dp);
    while(t--)
    {
        scanf("%d%d",&A,&B);
        int ans=0;
        ans=get();
        printf("Case #%d: %d\n",++tt,ans);
    }
    return 0;
}
</span>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值