首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 其他相关 >

简略数位dp-hdu-4734-F(x)

2013-09-17 
简单数位dp-hdu-4734-F(x)题目链接:http://acm.hdu.edu.cn/showproblem.php?pid4734题目大意:给一个数A (

简单数位dp-hdu-4734-F(x)

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4734

题目大意:

给一个数A (十进制表示形式为AnAn-1An-2 ... A2A1,定义函数 F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1,给一个B,求B以内的i,满足F(i)<=F(A)

解题思路:

很裸的数位dp,先求出F(A),dp[i][j]:表示有i位不超过j的有多少个。

PS:开始傻逼的用dp[i][j]表示有i位前面的一共占了多少,这样的话只对特定的样例有点减枝,对所有样例没有减枝,思维转的不灵活。

代码:

#include<iostream>#include<cmath>#include<cstdio>#include<cstdlib>#include<string>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#define eps 1e-6#define INF 0x3fffffff#define PI acos(-1.0)#define ll __int64#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;int a,b;int sa[22];int bit[30],num;int lim;int Cal(int aa){    int res=0;    int cnt=0;    while(aa)    {        res+=(aa%10)*sa[cnt]; //求F(A)        cnt++;        aa/=10;    }    return res;}int dp[22][11000];ll dfs(int cur,int la,int flag){    if(!cur)    {        if(!flag)            dp[cur][la]=1;        return 1;    }    if(dp[cur][la]!=-1&&!flag) //记忆话搜索        return dp[cur][la];    int Max=flag?bit[cur]:9;    ll res=0;    for(int i=0;i<=Max;i++)    {        if(la<i*sa[cur-1])            continue;        res+=dfs(cur-1,la-i*sa[cur-1],flag&&(i==Max));    }    if(!flag)        dp[cur][la]=res;    return res;}ll init(int x){    num=0;    while(x)    {        bit[++num]=x%10; //分离出每一位(十进制)        x/=10;    }    return dfs(num,lim,1);}int main(){    int t;    sa[0]=1;    for(int i=1;i<=10;i++) //sa[i]=2^i        sa[i]=sa[i-1]*2;    scanf("%d",&t);    memset(dp,-1,sizeof(dp));    for(int ca=1;ca<=t;ca++)    {        scanf("%d%d",&a,&b);        lim=Cal(a); //求出F(A)        printf("Case #%d: %d\n",ca,init(b));    }   return 0;}



热点排行