zoukankan      html  css  js  c++  java
  • CF 给你三个数字L, R, K,问在[L, R]范围内有多少个数字满足它每一位不同数字不超过k个,求出它们的和(数位DP)

    题意:

    给你三个数字L, R, K,问在[L, R]范围内有多少个数字满足它每一位不同数字不超过k个,求出它们的和

     

    分析:考虑用状态压缩 , 10给位0~9 , 如果之前出现过了某个数字x ,那就拿当前的状态 st | (1<<x) , 表示这个数字出现了 , 那st的二进制有多少的1 , 就有多少不同的数 , 这里好要考虑前导零的情况 。

    个数是解决了 , 但是这里是要每个答案的和 , 贼鸡儿坑 , 经过前面的训练可以知道不可能是在(len==0) 这里判断的了 , 因为是记忆化搜索 , 所以你记忆化的只是数量 ,而不是权值和 , 我们可以开多一个位来统计当前位的权值和 , 我们也很容易可以发现 ,并不是单纯的相加起来 , 还要相乘与符合条件 ;

    举例子:112和114都是满足条件的权值和 ;(112+114)=(100+10+2+100+10+4)=(2*100+2*10+2+4) 

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll MOD = 998244353ll;
    int cnt[20];
    ll ppow[22];
    ll a,b,k;
    struct Point{
        ll x,y;//x代表符合条件的有几个,y代表对答案的贡献
    }dp[20][1<<12][2];
    Point dfs(ll len,ll state,bool limit,bool non_zero){
        if(len==0) return Point{1,0};//一个数字枚举完了 符合条件的++ 不再产生贡献(之前已经计算了)
        if(!limit&&dp[len][state][non_zero].y) return dp[len][state][non_zero];
        //记忆化
        Point ans = Point{0,0};//初始化ans
        int Max = limit?cnt[len]:9;//套路
        for(int i=0;i<=Max;++i){
            ll temp = state|((non_zero||i)<<i); //改变状态
            if(__builtin_popcountll(temp)>k) continue;//删掉错误的状态
            Point t = dfs(len-1,temp,limit&&i==Max,non_zero||i);//临时变量
            ans.x = (ans.x+t.x)%MOD;//符合条件的个数增加
            ans.y = (ans.y+t.y+i*ppow[len-1]%MOD*t.x%MOD)%MOD;//当前数位的贡献增加
        }
        return dp[len][state][non_zero]=ans;
    }
    ll solve(ll x){
        memset(dp,0,sizeof dp);
        memset(cnt,0,sizeof cnt);
        int len=0;
        while(x){
            cnt[++len]=x%10;
            x/=10;
        }
        return dfs(len,0,true,0).y;
        //最高位开始枚举 现在还没有任何数位上有数字 到达了最高位 有前导零zero=true non_zero = false
    }
    int main(){
        ppow[0]=1;
        for(int i=1;i<20;++i) ppow[i]=ppow[i-1]*10%MOD;
        ios::sync_with_stdio(0);
        cin>>a>>b>>k;
        cout<<(solve(b)-solve(a-1)+MOD)%MOD<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    第十五篇:在SOUI中消息通讯
    为GDI函数增加透明度处理
    第十四篇:在SOUI中使用定时器
    第十三篇:在SOUI中使用有窗口句柄的子窗口
    第十二篇:SOUI的utilities模块为什么要用DLL编译?
    第十一篇:SOUI系统资源管理
    第十篇:扩展SOUI的控件及绘图对象(ISkinObj)
    第九篇:在SOUI中使用多语言翻译
    第八篇:SOUI中控件事件的响应
    Linked List Cycle
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9967607.html
Copyright © 2011-2022 走看看