zoukankan      html  css  js  c++  java
  • 题解——HDU 4734 F(x) (数位DP)

    这道题还是关于数位DP的板子题

    数位DP有一个显著的特征,就是求的东西大概率与输入关系不大,理论上一般都是数的构成规律

    然后这题就是算一个( F(A) )的公式值,然后求( left [ 0 ,  B ight ] )区间内( F(x) )不大于( F(A) )的数的个数

    所以由数据范围很容易得到计算出最大值不会超过4600

    然后我们设状态( dp[10][4600][4600] )表示不同( F(A) )取值下的第( pos )个位置的值总和为 ( sumx )的 数的个数

    显然会MLE

    这时候可以用减法转换状态

    用( dp[10][4600] )表示到了第( pos )个位置,还要凑( sumx )的值的数的个数

    然后就可以发现一个现象,这个状态与( F(A) )无关的

    然后就可做了

    注意一个事情,就是求的是不大于( F(A) )的数的个数

    所以最后( sumx ge 0 )就是合法状态了

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    int dp[10][4600],a[10];
    int dfs(int pos,int limit,int state){
      if(state<0)
        return 0;
      if(pos==-1){
        return state>=0;
      }
      if(!limit&&dp[pos][state]!=-1)
        return dp[pos][state];
      int mid=0,up=limit?a[pos]:9;
      for(int i=0;i<=up;i++){
        if((i<<(pos))<=state)
          mid+=dfs(pos-1,limit&&i==a[pos],state-(i<<(pos)));
      }
      if(!limit)
        dp[pos][state]=mid;
      return mid;
    }
    int solve(int A,int x){
      int fa=0,cona=0;
      while(A){
        fa+=((A%10)<<(cona));
        A/=10;
        cona++;
      }
      int con=0;
      memset(a,0,sizeof(a));
      while(x){
        a[con]=x%10;
        x/=10;
        con++;
      }
      return dfs(con-1,true,fa);
    }
    int main(){
      int T;
      memset(dp,-1,sizeof(dp) );
      scanf("%d",&T);
      for(int i=1;i<=T;i++){
        int A,B;
        scanf("%d %d",&A,&B);
        printf("Case #%d: %d
    ",i,solve(A,B));
      }
      return 0;
    }
  • 相关阅读:
    Jenkins使用msbuild编译问题记录
    mui的l label下radio问题
    JavaScript {} 和[]的区别 post提交数据
    闭包
    自我介绍
    激活码
    Excel的Xlsb格式的优点及缺点,与xlsx xlsm格式的区别
    oracle 数据类型 number
    iOS 14 更新后微信等应用 发送图片只能选择最近的项目
    plsql 恢复文件
  • 原文地址:https://www.cnblogs.com/dreagonm/p/9584647.html
Copyright © 2011-2022 走看看