• HDU3734 F(x)


    题目描述

    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.

    题解

    可以观察到位数只有9位,F(x)的值不会超过4599,那么很容易可以得到状态f[pos][sum]

    #include<bits/stdc++.h>
    using namespace std;
    
    int t,pow2[15];
    int a,b;
    int len,num[10];
    int f[10][10000][2];
    
    void get_fa(int &a){
        int x=0,cnt=0;;
        while(a){
            x+=pow2[cnt++]*(a%10);
            a/=10;
        }
        a=x;
    }
    
    int dfs(int s,int sum,bool lim){
        if(sum>a) return 0;
        if(!s) return 1;
        if(f[s][sum][lim]!=-1) return f[s][sum][lim];
        int mx= lim ? num[s] : 9 ;
        int ret=0;
        for(int i=0;i<=mx;i++)
         ret+=dfs(s-1,sum+i*pow2[s-1],lim&&i==mx);
        return f[s][sum][lim]=ret;
    }
    
    int cx(int x){
        len=0;
        while(x){
            num[++len]=x%10;
            x/=10;
        }
        memset(f,-1,sizeof(f));
        return dfs(len,0,true);
    }
    
    void nice(int i){
        scanf("%d%d",&a,&b);
        get_fa(a);
        //printf("%d
    ",a);
        printf("Case #%d: %d
    ",i,cx(b));
    }
    
    int main(){
        pow2[0]=1;
        for(int i=1;i<=10;i++) pow2[i]=pow2[i-1]*2;
        scanf("%d",&t);
        for(int i=1;i<=t;i++) nice(i);
    }
    View Code

    然后疯狂TTTTTTT掉

    因为对于每组数据都要将f初始化,然后不要脸的去看了博客

    发现可以改变数组状态,第二位定义为与f(x)的差,就只需要在最初初始化,不过不能开lim这一维

    简直妙啊

    #include<bits/stdc++.h>
    using namespace std;
    
    int t,pow2[15];
    int a,b;
    int len,num[10];
    int f[10][4600];
    
    void get_fa(int &a){
        int x=0,cnt=0;;
        while(a){
            x+=pow2[cnt++]*(a%10);
            a/=10;
        }
        a=x;
    }
    
    int dfs(int s,int sum,bool lim){
        if(sum<0) return 0;
        if(!s) return 1;
        if(!lim&&f[s][sum]!=-1) return f[s][sum];
        int mx= lim ? num[s] : 9 ;
        int ret=0;
        for(int i=0;i<=mx;i++)
         ret+=dfs(s-1,sum-i*pow2[s-1],lim&&i==mx);
        if(!lim) f[s][sum]=ret;
        return ret;
    }
    
    int cx(int x){
        len=0;
        while(x){
            num[++len]=x%10;
            x/=10;
        }
        return dfs(len,a,true);
    }
    
    void nice(int i){
        scanf("%d%d",&a,&b);
        get_fa(a);
        //printf("%d
    ",a);
        printf("Case #%d: %d
    ",i,cx(b));
    }
    
    int main(){
        pow2[0]=1;
        for(int i=1;i<=10;i++) pow2[i]=pow2[i-1]*2;
        memset(f,-1,sizeof(f));
        scanf("%d",&t);
        for(int i=1;i<=t;i++) nice(i);
    }
    View Code
  • 相关阅读:
    LeetCode 1109 航班预定统计
    leetcode 138 复制带随机指针的链表
    maven导入org.apache.pdfbox
    Intellij Idea 通过svn或者git提交代码时速度慢的解决办法
    java LocalDateTime 加减当前时间
    git命令--拉取代码和切换分支
    Intellij IDEA插件Free Mybatis plugin
    MySQL 生成随机字符串 uuid
    最新版Navicat Premium v15.0.26 中文破解
    算法——二分法查找
  • 原文地址:https://www.cnblogs.com/sto324/p/11206620.html
Copyright © 2020-2023  润新知