• 洛谷


    https://www.luogu.org/problemnew/show/P2602

    第二道数位dp,因为“数位dp都是模板题”(误),所以是从第一道的基础上面改的。

    核心思想就是分类讨论,分不同情况讨论对答案的贡献。

    最最重要的是,该数位取与当前位相等的时候,贡献的个数是受这个数位影响的所有数(这个写法里包括它本身),那么就用x减去与x前缀相同的“整数”再+1就可以算出来了。

     其他的数位dp……好像就不太会写了,再研究一下。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll dp[14][10][10];
    ll pow10[14];
    
    ll sum(int i,int j1,int j2,int k){
        if(j1<0)
            j1=0;
        if(j2>9)
            j2=9;
        ll res=0;
        for(int j=j1;j<=j2;j++){
            res+=dp[i][j][k];
        }
        return res;
    }
    
    void init(){
        pow10[0]=1;
        for(int i=1;i<=13;i++){
            pow10[i]=pow10[i-1]*10;
        }
    
        for(int j=0;j<=9;j++)
            dp[1][j][j]=1;
        for(int i=2;i<=13;i++){
            for(int j=0;j<=9;j++){
                for(int k=0;k<=9;k++){
                    dp[i][j][k]=sum(i-1,0,9,k);
                    if(j==k){
                        dp[i][j][k]+=pow10[i-1];
                    }
                }
            }
        }
    
        /*for(int j=1;j<=2;j++){
            dp[9][j]=sum(8,0,j-2)+sum(8,j+2,9);
        }*/
    
        /*for(int i=1;i<=13;i++){
            for(int j=0;j<=9;j++){
                for(int k=0;k<=9;k++)
                    printf("dp[%d][%d][%d]=%d
    ",i,j,k,dp[i][j][k]);
            }
            printf("
    ");
        }*/
    }
    
    ll A,B;
    int digit[14];
    
    int w;
    
    ll count(ll x){
        //cout<<"x="<<x<<endl;
        if(x<0)
            return 0;
        if(x==0){
            if(w==0)
                return 1;
            else
                return 0;
        }
        //否则岂不是0位数?
        ll k=0,cx=x;
        digit[k++]=0;
        //占位用的
        while(cx){
            digit[k++]=cx%10;
            cx/=10;
        }
        k--;
        digit[k+1]=0;
        //也是占位
    
        ll res=0;
        for(int i=k;i>=1;i--){
            //printf("i=%d res=%d
    ",i,res);
            if(i==k){
                //最高位取0
                for(int ii=i-1;ii>=1;ii--){
                    res+=sum(ii,1,9,w);
                    //printf("you want=%d
    ",res);
                }
                if(w==0)
                    res+=1;//0
                //其实不用特判啊
                for(int j=1;j<digit[i];j++){
                    //最高位比digit小且不为0
    
                    if(i-1>=1){
                        if(j==w)
                            res+=pow10[i-1];
                        res+=sum(i-1,0,9,w);
                    }
                    else{
                        if(j==w)
                            res+=1;
                    }
                }
                //最高位就取相等,问题留给下一次循环
                //取相等怎么会是满的呢?
                if(digit[i]==w)
                    res+=(x-x/pow10[i-1]*pow10[i-1]+1);
            }
            else{
                //前面的位都相等,非最高位的情况
                for(int j=0;j<digit[i];j++){
                    if(i-1>=1){
                        if(j==w)
                            res+=pow10[i-1];
                        res+=sum(i-1,0,9,w);
                    }
                    else{
                        if(j==w)
                            res+=1;
                    }
                }
                if(digit[i]==w)
                    res+=(x-x/pow10[i-1]*pow10[i-1]+1);
            }
        }
    
        //一直相等的情况在上面自动处理了,不用另外处理
        /*for(int i=1;i<=k;i++){
            if(digit[i]==w){
                res++;
            }
        }*/
        //printf("res=%d
    ",res);
        return res;
    }
    
    int main(){
        init();
        while(~scanf("%lld%lld",&A,&B)){
            for(w=0;w<=9;w++)
                printf("%lld%c",count(B)-count(A-1)," 
    "[w==9]);
        }
    }

    后来学会了搜索写法。

  • 相关阅读:
    AngularJS $http模块POST请求
    thinkphp整合系列之融云即时通讯在线聊天
    Linux 常用命令
    Linux Shell脚本编写规范、例子
    Linux crontab定时执行任务 命令格式与详细例子
    Linux目录详细说明大全, 方便你以后合理规划及管理
    Linux 操作MySQL常用命令行
    SVN服务器搭建和使用(三)
    Linux下的SVN服务器搭建
    python 根据染色体起始终止点坐标来获取碱基序列
  • 原文地址:https://www.cnblogs.com/Yinku/p/10325298.html
Copyright © 2020-2023  润新知