zoukankan      html  css  js  c++  java
  • hdu 4734 F(x)(数位dp)

    Problem Description
    For a decimal number x with n digits (AnAn-1An-2 ... A2A1), we define its weight as F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there between 0 and B, inclusive, whose weight is no more than F(A).
     
    Input
    The first line has a number T (T <= 10000) , indicating the number of test cases.
    For each test case, there are two numbers A and B (0 <= A,B < 109)
     
    Output
    For every case,you should output "Case #t: " at first, without quotes. The t is the case number starting from 1. Then output the answer.
     
    Sample Input
    3
    0 100
    1 10
    5 100 
     
    Sample Output
    Case #1: 1
    Case #2: 2 Case #3: 13
     
    题意:题目给了个f(x)的定义:F(x) = An * 2n-1 + An-1 * 2n-2 + … + A2 * 2 + A1 * 1,Ai是十进制数位,然后给出a,b求区间[0,b]内满足f(i)==f(a)的i的个数。
    思路:最开始的思路是dp[len][sum] 然后每次都memset果断tle 然后觉的开三维 空间又过不了 看聚聚的题解知道可以用总和的思想来减去当前的权值
    仔细想想这个状态是与f(a)无关的,一个状态只有在sum=0时才满足,如果我们按常规的思想求f(i)的话,那么最后sum=f(a)才是满足的条件。
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<stack>
    #include<bitset>
    #include<cstdlib>
    #include<cmath>
    #include<set>
    #include<list>
    #include<deque>
    #include<map>
    #include<queue>
    #define ll long long int
    using namespace std;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    int dir[2][2]={1,0 ,0,1};
    int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
    const int inf=0x3f3f3f3f;
    int bits[10];
    int dp[10][10007]; //len位 需要凑sum的权值和 
    int fa;
    int v[11]={1,2,4,8,16,32,64,128,256,512};
    int dfs(int len,int sum,bool ismax){
        if(!len) return sum<=fa;
        if(sum>fa) return 0;
        if(!ismax&&dp[len][fa-sum]>=0) return dp[len][fa-sum];
        int up=ismax?bits[len]:9;
        int cnt=0;
        for(int i=0;i<=up;i++){
            cnt+=dfs(len-1,sum+i*v[len-1],ismax&&i==up);
        }
        if(!ismax) dp[len][fa-sum]=cnt;
        return cnt;
    }
    int solve(int x){
        int len=0;
        while(x){
            bits[++len]=x%10;
            x/=10;
        }
        return dfs(len,0,true);
    }
    void cal(int a){
        int now=1;
        while(a){
            fa+=now*(a%10);
            a/=10; now*=2;
        }
    }
    int main(){
        int t;
        scanf("%d",&t);
        int w=0;
        memset(dp,-1,sizeof(dp));
        while(t--){
            fa=0;    
            int a,b; 
            scanf("%d%d",&a,&b);
            cal(a);
            printf("Case #%d: %d
    ",++w,solve(b));
        }
        return 0;
    }
     
     
  • 相关阅读:
    Spring:(八) mybatis-spring整合
    Spring:(七) Aop
    spring boot中@ControllerAdvice的用法
    spring boot中注册拦截器
    spring boot 中通过CORS实现跨域
    spring boot 中的路径映射
    浅析java中的string
    java并发编程如何预防死锁
    Redis集群增加节点和删除节点
    Redis删除集群以及重新启动集群
  • 原文地址:https://www.cnblogs.com/wmj6/p/10817174.html
Copyright © 2011-2022 走看看