zoukankan      html  css  js  c++  java
  • 2020杭电多校第三场 1006- X Number 数位dp

    1006- X Number

    题意

    给你两个整数 (l,r) 和一个数码 (d) ,问在 ([l,r]) 范围内有多少个数中数码 (d) 出现的次数严格大于其他数码出现的次数。

    分析

    如果直接数位(dp)需要存每个数字出现的次数,数组是开不下的,但是可以利用对(limit)的理解来做:

    (limit)表示当前枚举的位有限制,表示前几位都和原数字(a_i)是相同的,所以当前这一位只能从(0)枚举到(a_i)

    当没有限制时,后面的数字就可以随便取,这时我们就可以直接计算答案了,用(cnt[i])记录枚举到当前位每个数字(i)出现了多少次,(pos)表示还有多少个剩余位置是空的,枚举数码(d)出现的次数(num),就可以大力(dp)了,状态(dp[i][j])表示考虑(0sim 9)中前(i)位且除了指定的那一位以外已经在剩余的位置安放了(j)个数。转移如下:

    [dp[i][j]=sum_{k=0}^{min(j,num-cnt[i]-1)}dp[i-1][j-k] imes C_{pos-j+k}^{k} ]

    这个转移可以自己手推一推。

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<sstream>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<bitset>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<set>
    #include<map>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=1e5+10;
    const int inf=1e9;
    int T,d;
    ll l,r;
    int cnt[11];
    ll dp[11][22],C[22][22];
    int a[22];
    ll dfs(int pos,int limit,int lead){
        if(pos==-1){
            int mx=0,num=0;
            rep(i,0,9)  if(cnt[i]>cnt[mx]) mx=i;
            rep(i,0,9) if(cnt[i]==cnt[mx]) num++;
            return mx==d&&num==1;
        }
        if(!limit&&!lead){
            ll ans=0;
            int mx=cnt[d];
            rep(i,0,9) if(i!=d) mx=max(mx,cnt[i]+1);
            for(int num=mx;num<=cnt[d]+pos+1;num++){
                memset(dp,0,sizeof(dp));
                dp[0][0]=1;
                rep(i,1,10){
                    if(i==d+1){
                        for(int j=0;j<=20;j++) dp[i][j]=dp[i-1][j];
                        continue;
                    }
                    for(int j=0;j<=cnt[d]+pos+1-num;j++){
                        for(int k=0;k<=num-cnt[i-1]-1&&j-k>=0;k++){
                            dp[i][j]+=dp[i-1][j-k]*C[pos+1-j+k][k];
                        }
                    }
                }
                ans+=dp[10][cnt[d]+pos+1-num];
            }
            return ans;
        }
        int up=limit?a[pos]:9;
        ll ans=0;
        for(int i=0;i<=up;i++){
            if(!lead||i!=0) cnt[i]++;
            ans+=dfs(pos-1,limit&&i==a[pos],lead&&i==0);
            if(!lead||i!=0) cnt[i]--;
        }
        return ans;
    }
    ll solve(ll x){
        int len=0;
        while(x){
            a[len++]=x%10;
            x/=10;
        }
        return dfs(len-1,true,true);
    }
    int main(){
        //ios::sync_with_stdio(false);
        //freopen("in","r",stdin);
        C[0][0]=1;
        rep(i,1,20){
            C[i][0]=1;
            rep(j,1,i){
                C[i][j]=C[i-1][j]+C[i-1][j-1];
            }
        }
        scanf("%d",&T);
        while(T--){
            scanf("%lld%lld%d",&l,&r,&d);
            printf("%lld
    ",solve(r)-solve(l-1));
        }
        return 0;
    }
    
  • 相关阅读:
    Service、chkconfig命令
    mongoDB 入门
    HTTP 缓存
    MIME类型记录
    CSS3 动画 思维导图
    部署Seafile服务
    AngularJS 学习笔记
    Bootstrap3 学习笔记
    CSS 弹性盒
    传送门(portal)
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13396464.html
Copyright © 2011-2022 走看看