ABC235 F Variety of Digits

Posted solemntee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ABC235 F Variety of Digits相关的知识,希望对你有一定的参考价值。


题意:给一个小于 1 0 1 0 4 10^10^4 10104的整数 N N N找不大于 N N N的满足数位中有 c 1 . . . c n c_1...c_n c1...cn的数字。
考虑数位 d p dp dp d p [ p o s ] [ s t a ] dp[pos][sta] dp[pos][sta]表示第 p o s pos pos位,数位中已经出现的数字种类情况是 s t a sta sta的方案数, d p 2 [ p o s ] [ s t a ] dp2[pos][sta] dp2[pos][sta]表示第 p o s pos pos位,数位中已经出现的数字种类情况是 s t a sta sta的贡献和,总体来讲是非常经典的题目。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int limit[10005];
ll dp[10005][3005];
ll dp2[10005][3005];
int M,c[14];
int mp[10];
char s[10005];
const int mod=998244353;
ll P[10005];
void init()

    P[0]=1;
    for(int i=1;i<=10000;i++)P[i]=P[i-1]*10%mod;

pair<ll,ll> dfs(int pos,int sta,bool lead,bool flag)

    if(pos==-1)
        return sta==((1<<M)-1),0;
    
    if(!flag&&!lead&&dp[pos][sta]!=-1)return dp[pos][sta],dp2[pos][sta];

    ll sum1=0,sum2=0,up=flag?limit[pos]:9;

    for(ll i=0;i<=up;i++)
    
        if(lead&&i==0)
        
            pair<ll,ll>p=dfs(pos-1,sta,true,flag&&i==limit[pos]);
            sum1=(sum1+p.first)%mod;
            sum2=(sum2+P[pos]*i%mod*p.first%mod+p.second)%mod;
        
        else if(mp[i]!=0)
        
            pair<ll,ll>p=dfs(pos-1,sta|(1<<(mp[i]-1)),false,flag&&i==limit[pos]);
            sum1=(sum1+p.first)%mod;
            sum2=(sum2+P[pos]*i%mod*p.first%mod+p.second)%mod;
        
        else
        
            pair<ll,ll>p=dfs(pos-1,sta,false,flag&&i==limit[pos]);
            sum1=(sum1+p.first)%mod;
            sum2=(sum2+P[pos]*i%mod*p.first%mod+p.second)%mod;
        
    
    if(!flag&&!lead)
    
        dp[pos][sta]=sum1;
        dp2[pos][sta]=sum2;
    

    return sum1,sum2;

int main()

    init();
    memset(dp,-1,sizeof(dp));
    memset(dp2,-1,sizeof(dp2));
    scanf("%s",s);
    int len=strlen(s);
    for(int i=0;i<len;i++)limit[i]=s[len-i-1]-'0';
    scanf("%d",&M);
    int asdf=0;
    for(int i=1;i<=M;i++)
    
        scanf("%d",&c[i]);
        mp[c[i]]=++asdf;
    

    printf("%lld\\n",dfs(len-1,0,true,true).second);
    return 0;

/*
104
2
0 1

301
301
2
0 1

300
300
2
0 1

299
299
2
0 1
*/

以上是关于ABC235 F Variety of Digits的主要内容,如果未能解决你的问题,请参考以下文章

Digit Sum II(ABC044&ARC060)

ABC 235 的 DE

ABC 235 的 DE

cf1556A. A Variety of Operations

#Leetcode# 233. Number of Digit One

233. Number of Digit One