P2602 [ZJOI2010]数字计数(数位dp)

题目传送门

题意: 给定两个正整数 a a a b b b,求在 [ a , b ] [a,b] [a,b] 中的所有整数中,每个数码(digit)各出现了多少次。

思路: 数位dp模板题,从0到9分别统计每个数位出现次数即可。

代码:

#include<bits/stdc++.h>
#define endl '\n'
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair<int,int>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
    int x=0,f=1;
    char ch=gc();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=gc();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=gc();
    }
    return x*f;
}
using namespace std;
const int N=2e5+50;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int a[N],len=0;
int f[15][N];
int ans[15][3],now=0;
int dfs(int pos,int st,int limit,int x,int cnt)
{
    if(pos==0) return cnt;
    if(!limit&&f[pos][cnt]!=-1 && !st) return f[pos][cnt];
    int high = limit?a[pos]:9,res=0;
    for(int i=0;i<=high;i++)
    {
        if(st&&i==0) res+=dfs(pos-1,st&&i==0,limit&&i==high,x,cnt);
        else res+=dfs(pos-1,st&&i==0,limit&&i==high,x,cnt+(i==x));
    }
    if(!limit && !st) f[pos][cnt]=res;
    return res;
}
void work(int x)
{
    len=0;
    while(x)
        a[++len]=x%10,x/=10;
    for(int i=0;i<=9;i++)
    {
        mem(f,-1);
        ans[i][now]=dfs(len,1,1,i,0);
    }
    now^=1;
}
void solve()
{
    int l,r;
    cin>>l>>r;
    work(l-1);
    work(r);
    for(int i=0;i<=9;i++)
        cout<<ans[i][1]-ans[i][0]<<" ";
    cout<<endl;
}
signed main()
{
//    int _;
//    cin>>_;
//    while(_--)
    solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值