• 2020 Multi-University Training Contest 3 1006 X Number


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6796

    题意:有11中类别,分别为0到10类别,如果某一个数他数中出现最多次数的是d(0<=d<=9),那这个数是d类别,比如233中3出现了2次,是最多的,所以是3类别,如果最多出现的不止一个数字,那就是10类别,比如22334,现在给你一个区间[l,r]和类别d(0<=d<=9),问你这个区间中有多少个数是d类别的。

    思路:首先肯定会想到数位dp,但会发现进行记忆化搜索时那个状态不好确定。这里就可以进行魔改,当你搜索到上一个数字已经不处于边界时,知道了d数字的个数已经其他数字的个数,就可以用组合数算出来。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll a[20],b[20],c[20][20];
    ll x,l,r;
    map<array<int,10>,ll>dp[20][2];
    array<int,10>state= {0};
    ll fun(int n,int m)
    {
        m=max(m,n-m);
        if(c[n][m]!=-1)
            return c[n][m];
        ll ans=1;
        for(int i=m+1; i<=n; i++)
            ans*=i;
        for(int i=1; i<=n-m; i++)
            ans/=i;
        return c[n][m]=ans;
    }
    ll dfs(int len,bool maxi,bool f)
    {
        if(dp[len][f].find(state)!=dp[len][f].end()&&maxi==0)
            return dp[len][f][state];
        if(!len)
        {
            for(int i=0; i<10; i++)
                if(i!=x&&state[i]>=state[x])
                    return dp[len][f][state]=0;
            return dp[len][f][state]=1;
        }
        ll res=0,maxn=maxi?a[len]:9;
        if(f&&!maxi)
        {
            for(int i=0; i<=len; i++)
            {
                for(int i0=0; i0<=len-i; i0++)
                    b[i0]=0;
                b[len-i]=fun(len,i);
                for(int i0=0; i0<10; i0++)
                {
                    if(i0==x)
                        continue;
                    if(state[x]+i<=state[i0])
                    {
                        b[0]=0;
                        break;
                    }
                    for(int i1=0; i1<=len-i; i1++)
                    {
                        for(int i2=1; i2<=min(i1,state[x]+i-state[i0]-1); i2++)
                        {
                            b[i1-i2]+=fun(i1,i2)*b[i1];
                        }
                    }
                }
                res+=b[0];
            }
            return dp[len][f][state]=res;
        }
        for(int i=0; i<=maxn; i++)
        {
            if(i||f)
            {
                if(i==x||state[i]+2<state[x]+len)
                {
                    state[i]++;
                    res+=dfs(len-1,maxi&&i==a[len],1);
                    state[i]--;
                }
            }
            else
                res+=dfs(len-1,maxi&&i==a[len],0);
        }
        return maxi?res:dp[len][f][state]=res;
    }
    ll div(ll tmp)
    {
        int p=0;
        while(tmp)
            a[++p]=tmp%10,tmp/=10;
        ll res=0;
        res+=dfs(p,1,0);
        return res;
    }
    int main()
    {
        memset(c,-1,sizeof(c));
        int T;
        cin>>T;
        while(T--)
        {
            for(int i=0; i<20; i++)
                for(int i1=0; i1<2; i1++)
                    dp[i][i1].clear();
            cin>>l>>r>>x;
            cout<<div(r)-div(l-1)<<endl;
        }
    }
    

      

  • 相关阅读:
    数据库常用的锁有哪些
    如何在vue3.0 vue-cli 3.x中使用jquery
    带你体验Vue2和Vue3开发组件有什么区别
    snf帆软FineReport安装,布署,配置-王春天
    SNF开发平台WinForm之--审核流使用方式
    Linux上安装服务器监视工具,名为pyDash。
    Linux上安装服务器监视工具,名为Scout_Realtime。
    bootstrap fileinput(帮助文档URL)
    【转】Windows下使用Graalvm将Javafx应用编译成exe
    【转】Windows下使用Graalvm将Javafx应用编译成exe
  • 原文地址:https://www.cnblogs.com/zcb123456789/p/13399698.html
Copyright © 2020-2023  润新知