• K


    K - Number with Bachelors 数位dp + 思维

    题目大意:

    定义一种数 Y:表示把Y分解,分解出来的每一位没有重复的,例如:101就不是Y这种数,123是Y这种数

    有n次查询,有两种查询操作:

    • 0 后面给两个数a,b,求a到b之间的Y这种数
    • 1 后面给定x,求第x大的Y数

    有两种不同进制的询问,十进制和16进制

    题解:

    很明显第一个种操作就是一个数位dp,第二种操作想清楚可以发现是一个二分+数位dp

    这个题目一定要注意进制之间的转化,建议写一个输入函数和输出函数,这样就可以统一处理10进制和16进制了。

    最后还要注意的是按照正常的数位dp(也就是我的这种写法) d 1 1这个样例会TLE,具体原因可以输入一下二分的mid就可以发现了,所以要把 1 这种操作的 x == 1特判掉,还有就是注意0这种操作的a可能是0,所以也要判断一下。

    细节比较多。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = (1<<16) + 10;
    typedef unsigned long long ull;
    ull dp[2][22][maxn];
    int type,a[100];
     
    ull dfs(int pos,int sta,int limit){
        if(pos==-1) return 1;
        int ty = (type==10)?0:1;
        if(dp[ty][pos][sta]!=-1&&!limit) return dp[ty][pos][sta];
        int up = limit?a[pos]:type - 1;
        ull ans = 0;
        for(int i=0;i<=up;i++){
            if((sta>>i)&1) continue;
            if(sta==0&&i==0) ans+=dfs(pos-1,sta,limit&&i==up);
            else ans+=dfs(pos-1,sta|(1<<i),limit&&i==up);
        }
        if(!limit) dp[ty][pos][sta] = ans;
        // printf("pos = %d sta = %d limit = %d ans = %llu
    ", pos,sta,limit,ans);
        return ans;
    }
     
    ull solve(ull x){
        int pos = 0;
        while(x){
            a[pos++] = x%type;
            x/=type;
        }
        return dfs(pos-1,0,true);
    }
     
    void input(ull &x){
        x = 0;
        char s[22];
        scanf("%s",s+1);
        int len = strlen(s+1);
        for(int i=1;i<=len;i++) {
            if(s[i]<='9'&&s[i]>='0') x = x * type + s[i] - '0';
            else x = x * type + s[i] - 'a' + 10;
        }
    }
    void print(ull x){
        if(x==0){
            printf("0
    ");
            return ;
        }
        if(type == 10) printf("%llu
    ", x);
        else{
            vector<int>ans;
            while(x){
                int p = x % type;
                x/=type;
                ans.push_back(p);
            }
            for(int i=ans.size()-1;i>=0;i--) {
                if(ans[i]>=10) printf("%c", ans[i] - 10 + 'a');
                else printf("%c", ans[i]+'0');
            }
            printf("
    ");
        }
    }
    void test(){
        int t;
        scanf("%d",&t);
        while(t--){
            int x;
            scanf("%d%d",&x,&type);
            printf("%llu",solve(x));
        }
    }
    int main(){
        memset(dp,-1,sizeof(dp));
        // test();
        int T;
        scanf("%d",&T);
        while(T--){
            char op[10];
            scanf("%s",op);
            if(op[0]=='d') type = 10;
            else type = 16;
            int flag;
            scanf("%d",&flag);
            if(!flag){
                ull a,b;
                input(a),input(b);
                // printf("ss a = %llu b = %llu
    ", a,b);
                ull ans = solve(b);
                if(a>0) ans-=solve(a - 1);
                print(ans);
            }
            else{
                ull x;
                input(x);
                if(x<10){
                    printf("%llu
    ", x - 1);
                    continue;
                }
                ull l = 0,r = 0,ans = 0;r--;
                if(solve(r)<x){
                    printf("-
    ");
                    continue;
                }
                while(l<=r){
                    ull mid = l + (r - l) / 2;
                    if(solve(mid)>=x) r = mid - 1,ans = mid;
                    else l = mid + 1;
                }
                print(ans);
            }
        }
    }
    
  • 相关阅读:
    php数组
    php数组排序
    php超级全局变量
    php循环
    php函数
    PHP魔术常量
    php面向对象
    static 关键字
    Final 关键字
    内置函数
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14045054.html
Copyright © 2020-2023  润新知