数位dp 不要62

纯纯数位dp板子,可以顺着思路下来。

传统技能学习笔记

不要62 libreoj

设状态为 \(dp[i][j]\) 为第 \(i\) 位是 \(j\) 的可能情况数。

枚举位数,这位的数,低一位的数,将每一位的组合可能存下来,但要把这位是 4 与这位是 6 低一位是 2 的情况排除掉。

void init(){
dp[0][0]=1;
for(int i=1;i<=8;i++){
for(int j=0;j<=9;j++){
if(j==4){
continue;
}
for(int k=0;k<=9;k++){
if((j==6&&k==2)){
continue;
}
dp[i][j]+=dp[i-1][k];
}
}
}
}

然后进行计算,将每一位存下来,循环 0-a[i]-1,因为a[i]不能直接取全部情况,注意这时要将这位是2高一位6的情况排除掉,这个可以思考思考就可以了。如果出现哪一位4和62的话直接跳出,因为后面一定就不会取到。

ll dig(int x){
int cnt=0;
ll sum=0;
while(x){
a[++cnt]=x%10;
x/=10;
}
a[cnt+1]=-1;
for(int i=cnt;i>=1;i--){
for(int j=0;j<a[i];j++){
if(j==2&&a[i+1]==6){
continue;
}
sum+=dp[i][j];
}
if(a[i]==4||(a[i+1]==6&&a[i]==2)){
break;
}
}
return sum;
}

这样计算时要r+1,因为最后一位总是取不到,所以要多打个1就可以了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m;
ll dp[15][15];
int a[15];
void init(){
dp[0][0]=1;
for(int i=1;i<=8;i++){
for(int j=0;j<=9;j++){
if(j==4){
continue;
}
for(int k=0;k<=9;k++){
if((j==6&&k==2)){
continue;
}
dp[i][j]+=dp[i-1][k];
}
}
}
}
ll dig(int x){
int cnt=0;
ll sum=0;
while(x){
a[++cnt]=x%10;
x/=10;
}
a[cnt+1]=-1;
for(int i=cnt;i>=1;i--){
for(int j=0;j<a[i];j++){
if(j==2&&a[i+1]==6){
continue;
}
sum+=dp[i][j];
}
if(a[i]==4||(a[i+1]==6&&a[i]==2)){
break;
}
}
return sum;
}
int main(){
ios::sync_with_stdio(false);
init();
while(1){
cin>>n>>m;
if(n==0&&m==0){
break;
}
cout<<dig(m+1)-dig(n)<<"\n";
}
return 0;
}
posted @   sad_lin  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示