HDOJ 4734 - F(x) 数位DP

                题意:

                        给出F(x)的运算..F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1..其中A1为十进制数x的个位..A2为其十位....现在给出A,B求0~B中F(x)比F(A)小的个数

                题解:

                        可以算出极限情况..999999999..得到的是4599..代表F(x)的值域是很小的..可以用数位DP来整..dp[t][y]代表长度为t的数..F(x)为y的个数..有了状态..转移小case了..不过数位DP是很容易错的..所以我还写了个暴力来对拍...


Program:

#include<iostream>
#include<stack>
#include<queue>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<cmath>
#define ll long long
#define oo 1000000007
#define eps 1e-5
#define MAXN 100010
using namespace std;  
int dp[12][6000];
void PreWork()
{
      int i,j,x,k,t=1;
      memset(dp,0,sizeof(dp)),dp[0][0]=1;
      for (i=1;i<=9;i++)
      {
           for (k=0;k<=4650;k++)
              for (j=0;j<=9;j++) 
                 dp[i][j*t+k]+=dp[i-1][k];     
           t<<=1;  
      }      
}
char c;
int _2jie[15],num[9];
int input()
{
      int x=0,i;
      do { c=getchar(); } while (c<'0' || c>'9');
      while (c>='0' && c<='9')
      {
              x=x*10+c-'0';
              c=getchar();
      }
      _2jie[0]=1,num[0]=9;
      for (i=1;i<=10;i++) _2jie[i]=1<<i,num[i]=9*_2jie[i]+num[i-1];
      return x;
}
char s[12];
int main()
{ 
      int C,cases,A,B,P,t,ans,  len,i,j,x,k; 
      PreWork(); 
      C=input();
      for (cases=1;cases<=C;cases++)
      {         
              A=input(),B=input();
              ans=P=0,t=1;
              while (A)
              {
                      P+=(A%10)*t;
                      t*=2,A/=10;
              }       
              //---------------------------  
              sprintf(s,"%d",B),len=strlen(s),t=0;
              for (i=len-1;i>=0;i--)
              {
                      for (j=0;j<s[len-i-1]-'0';j++)
                         for (x=0;x<=num[i];x++) //1!!!
                         {
                                 if (j*_2jie[i]+x+t>P) break; 
                                 ans+=dp[i][x];
                         }
                      t+=(s[len-i-1]-'0')*_2jie[i];
                      if (t>P) break;
              }
              if (t<=P) ans++;
              //---------------------------
              printf("Case #%d: %d\n",cases,ans);
      }
      return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值