洛谷P2188 小Z的 k 紧凑数

P2188 小Z的 k 紧凑数

题目描述

小 Z 在草稿纸上列出了很多数,他觉得相邻两位数字差的绝对值不超过 k 的整数特别奇特,称其为 k 紧凑数。

现在小 Z 想知道 [l,r] 内有多少个 k 紧凑数,希望你帮帮他。

输入输出格式

输入格式:

第一行包含三个整数 l,r,k。

输出格式:

第一行包含一个整数,表示 [l,r] 内 k 紧凑数的个数。

输入输出样例

输入样例#1:
1 13 1
输出样例#1:
12

说明

【数据规模】

对于 30% 的数据,r − l ≤ 10^5;

对于另外 30% 的数据,l = 1,r 为 10 的倍数;

对于 100% 的数据,1 ≤ l ≤ r ≤ 10^18,0 ≤ k ≤ 8。

#include<iostream>
#include<cstdio>
using namespace std;
long long l,r;
int k,len,bin[20],b[20];
long long dfs(int pos,int pre,int limit,int lead){
    if(pos==len+1)return 1;
    int end=limit?bin[pos]:9;
    long long ans=0;
    if(pos==1){
        for(int i=0;i<=end;i++)
            ans+=dfs(pos+1,i,limit&&i==end,lead&&i==0);
    }
    else if(lead){
        for(int i=0;i<=end;i++)
            ans+=dfs(pos+1,i,limit&&i==end,lead&&i==0);
    }
    else{
        for(int i=max(0,pre-k);i<=min(pre+k,end);i++)
            ans+=dfs(pos+1,i,limit&&i==end,lead&&i==0);
    }
    return ans;
}
long long work(long long x){
    len=0;
    while(x){
        b[++len]=x%10;
        x/=10;
    }
    for(int i=1,j=len;i<=len;i++,j--)bin[i]=b[j];
    return dfs(1,0,1,1);
}
int main(){
    freopen("Cola.txt","r",stdin);
    scanf("%d%d%d",&l,&r,&k);
    cout<<work(r)-work(l-1);
}
30分 暴力枚举数的每一位
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdlib>
#define int long long
using namespace std;
int f[21][11],x,y,m,bin[21];
int dp(int x){
    if(x==0)return 1;
    bin[0]=0;while(x)bin[++bin[0]]=x%10,x/=10;
    if(bin[0]==1)return bin[1]+1;
    int ans=1;
    for(int i=1;i<bin[0];i++)
        for(int j=1;j<10;j++)ans+=f[i][j];
    for(int i=1;i<bin[bin[0]];i++)ans+=f[bin[0]][i];
    for(int i=bin[0]-1;i;i--){
        if(i<bin[0]-1&&abs(bin[i+1]-bin[i+2])>m)return ans;
        for(int j=0;j<bin[i];j++)if(abs(j-bin[i+1])<=m)ans+=f[i][j];
    }
    if(abs(bin[1]-bin[2])<=m)ans++;return ans;
}
signed main(){
    freopen("Cola.txt","r",stdin);
    cin>>x>>y>>m;
    for(int i=0;i<10;i++)f[1][i]=1;
    for(int i=2;i<=18;i++)
        for(int j=0;j<10;j++)
            for(int k=0;k<10;k++)if(abs(j-k)<=m)f[i][j]+=f[i-1][k];
    cout<<dp(y)-dp(x-1);
    return 0;
}
100分 数位dp
原文地址:https://www.cnblogs.com/thmyl/p/7495488.html