zoukankan      html  css  js  c++  java
  • 2020 ICPC 台北区域赛 K

    题意:

    一个数如果没有任何两位的数字是相同的,则该数称为B数,有两种询问:

    • 问[a,b]区间有多少个B数(在10/16进制下)
    • 问第k个B数是什么(在10/16进制下)

    思路:

    显然第一类问题可以用数位DP求解,第二类问题就是在数位dp外面套个二分就可以求解。由于输入的数都是unsigned long long,有一些细节需要注意,比如边界特判等。二分的时候采用左开右闭,因为如果[0,a]存在k个B数,那么此时二分的右边界就是a,且可以取到。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ull;
    inline bool test(int x,int y){
        if((x>>y)&1)return 1;
        else return 0;
    }
    char domin;
    int a[21],len;
    ull dp[21][1<<16|1][2][2];
    ull dfs(int pos,int limit,int lead,int st,int base){
        if(pos==0) return !lead;
        if(!limit && dp[pos][st][lead][base==10?0:1]!=-1)
            return dp[pos][st][lead][base==10?0:1];
        ull ans=0;
        int maxx=limit?a[pos]:base-1;
        for(int i=0;i<=maxx;i++){
            if(!test(st,i)){
                ans+=dfs(pos-1,limit&&i==maxx,lead&&i==0,(lead&&i==0)?0:st|(1<<i),base);
            }
        }
        if(!limit) dp[pos][st][lead][base==10?0:1]=ans;
        return ans;
    }
    ull solve1(ull x){
        len=0;
        int base=domin=='d'?10:16;
        while(x){
            a[++len]=x%base;
            x/=base;
        }
        return dfs(len,1,1,0,base);
    }
    void input(ull &a){
         if(domin=='d')
            scanf("%llu",&a);
         else{
            a=0;
            char ch=getchar();
            while(!(ch>='0' && ch<='9')&&!(ch>='a' && ch<='f')) ch=getchar();
            while( (ch>='0' && ch<='9')||(ch>='a' && ch<='f') ){
                a=a*16;
                if(ch>='a')
                    a+=10+ch-'a';
                else
                    a+=ch-'0';
                ch=getchar();
            }
         }
    }
    void print(ull a){
        if(a==0){
            puts("0");return;
        }
        if(domin=='d'){//10
            printf("%llu
    ",a);return;
        }
        //16
        vector<int>ans;
        while(a){
            ans.push_back(a%16);
            a/=16;
        }
        for(int i=ans.size()-1;i>=0;i--){
            if(ans[i]>=10)
                printf("%c",'a'+ans[i]-10);
            else
                printf("%d",ans[i]);
        }
        puts("");
    }
    int main () {
        domin='h';
        memset(dp,-1,sizeof dp);
        int T;
        scanf("%d",&T);
        while(T--){
            ull a,b,i;
            scanf(" %c",&domin);
            int typ;scanf("%d",&typ);
            if(typ==0){
                input(a);
                input(b);
                ull ans=solve1(b);
                if(a==0)ans++;
                else{
                    ans-=solve1(a-1);
                }
                print(ans);
            }
            else{
                input(i);
                if(i<9){
                    printf("%llu
    ",i-1);
                    continue;
                }
                ull l=0,r=0;r--;
                if(solve1(r)<i-1){
                    puts("-");
                    continue;
                }
                while(r-l>1){//zkyb
                    ull mid=(r>>1)+(l>>1);
                    if((r&1)&&(l&1))mid++;
                    if(solve1(mid)<i-1)
                        l=mid;
                    else
                        r=mid;
                }
                print(r);
            }
        }
    }
    
  • 相关阅读:
    java实现土地测量
    java实现土地测量
    java实现土地测量
    java实现土地测量
    ajax异步获取数据后动态向表格中添加数据(行)
    jquery如何通过ajax请求获取后台数据显示在表格上
    Eclipse4.5在线安装Aptana插件及配置代码提示教程
    eclipse安装Aptana 插件,并设置使之能提示css,js,html,帮助编写代码
    jsp页面根据json数据动态生成table
    Jquery根据JSON生成Table
  • 原文地址:https://www.cnblogs.com/ucprer/p/14000652.html
Copyright © 2011-2022 走看看