数位dp题集

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define pb push_back

int a[12];
int f[12][10];//i位数字,最高位为j的windy数的数量

//注意这个题没有前导0
void init(){//由低位向高位传递,预处理
	for (int i=0;i<=9;i++) f[1][i]=1;
	for (int i=2;i<12;i++){  
		for (int j=0;j<=9;j++){
			for (int k=0;k<=9;k++){
				if (abs(k-j)>=2) f[i][j]+=f[i-1][k];   
			}
		}
		
	}
	
	
}

int dp(int x){
	if (!x) return 0;  //0不是windy数
	int cnt=0;
	while (x) a[++cnt]=x%10,x/=10;
	
	int res=0,last=-2;//是-2
	for (int i=cnt;i>=1;i--){ //从高位向低位枚举
		int now=a[i];
		for (int j=(i==cnt);j<now;j++) 
		if (abs(j-last)>=2)  res+=f[i][j];
		
		if (abs(now-last)<2) break;
		last =now;
		if (i==1) res++;
	
	}
	
	for (int i=1;i<cnt;i++){
		for (int j=1;j<=9;j++){
			res+=f[i][j];
		}
	}
	return res;
}


int main(){
	
	init();
	int l,r;
	cin>>l>>r;
	cout<<dp(r)-dp(l-1)<<endl;
	
}









#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define pb push_back
#define inf 0x3f3f3f3f


int a[12],cnt=0;
int dp[12][10];
int l,r;


void init (){
	for (int i=0;i<=9;i++) dp[1][i]=1;
	for (int i=2;i<12;i++){
		for (int j=0;j<=9;j++){
			for (int k=j;k<=9;k++) dp[i][j]+=dp[i-1][k];
		}
	}	
}


int dp1(int x){
	cnt=0;
	if (!x) return 1;
	while (x) a[++cnt]=x%10, x/=10;
	int res=0,last=0;
	for (int i=cnt;i>0;i--){
		int now=a[i];
		for (int j=last;j<now;j++){
			res+=dp[i][j];
		}
		if (now<last) break;
		last=now;
		if (i==1) res++;
		
		
	}
	return res;
	
}

int main(){
	init();
	while(cin>>l>>r){
		cout<<dp1(r)-dp1(l-1)<<endl;
	}
	
	
	
}

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define pb push_back
#define inf 0x3f3f3f3f


int a[12],cnt=0;
ll  dp[15][2][15][2];
ll l,r;

ll dfs(int len ,bool issmall,int sum,bool zero,int d){
// issmall =0 表示可能顶格,=1表示不会顶格
//sum 表示数字d的出现次数
//zero =1 表示这一位之前还全是前导零, =0 表示是正常的数了
	ll res=0;
	if (len==0) return sum;
	if (dp[len][issmall][sum][zero] !=-1 ) return dp[len][issmall][sum][zero];
	for (int i=0;i<10;i++){
		if (!issmall and i>a[len]) break;
		res+=dfs(len-1,issmall or(i<a[len]),sum+((!zero||i) and (i==d)), zero and i==0 ,d );
	}
	dp[len][issmall][sum][zero]=res;
	return res;
	
}

ll dp1(ll x,int d){
	int len=0;
	while (x) a[++len]=x%10,x/=10;
	memset(dp,-1,sizeof(dp));
	return dfs(len,0,0,1,d);
	
}

int main(){
	cin>>l>>r;
	for (int i=0;i<10;i++){
		cout<<dp1(r,i)-dp1(l-1,i)<<((i==9)?"\n":" ");
		
	}
	
	
	
}

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define pb push_back
#define inf 0x3f3f3f3f


int a[12],cnt=0;
ll  dp[12][10][100];
ll  l,r;
int n;

void init(){
		
	for (int i=0;i<10;i++){
		
		int mid=0;
		 mid=i%n;

		dp[1][i][mid]=1;
		
	}

	for (int i=2;i<12;i++){
		for (int j=0;j<10;j++){
			for (int p=0;p<10;p++){
				for (int k=0;k<n;k++){
				int mid=(j+k)%n;
				dp[i][j][mid]+=dp[i-1][p][k];
			}
			}

			
		}
		
	}

}

ll dp1(ll x){
			cnt=0;
	if (!x) return 0;
	while (x) a[++cnt]=x%10, x/=10;
	int mid=0;ll res=0;
	for (int i=cnt ;i>0;i--){
		for (int j=(i==cnt);j<a[i];j++){
			for (int k=0;k<n;k++){
				if ((mid+k)%n==0) res+=dp[i][j][k];
			}
		}
		mid+=a[i];

		mid%=n;

		if (i==1 and mid==0) res++;
	}

	for (int i=1;i<cnt;i++){
		for (int j=1;j<10;j++){
			res+=dp[i][j][0];
		}
	}

	return res;
}


int main(){
	while (cin>>l>>r>>n){

		memset(dp,0,sizeof (dp));
	init();

	
	
	cout<<dp1(r)-dp1(l-1)<<endl;

	}
	
	
	
}

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define pb push_back
#define inf 0x3f3f3f3f


int a[34],cnt=0;
ll  dp[34][34];
ll  l,r;
int n;


void init(){
	for (int i=0;i<34;i++) dp[i][0]=1,dp[i][i]=1;
	dp[1][1]=1;
	for(int i=2;i<34;i++){
		for (int j=1;j<i;j++){
			dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
		}
	}
}



ll dp1(ll x){
	cnt=0;
	if (!x) return 1;
	while (x) a[++cnt]=x%2,x/=2;
	ll res=0;
	for (int i=cnt-1;i>0;i--){
		for (int j=0;j<=i/2-1;j++){
			res+=dp[i-1][j];
		}
	}
	res++;
	
	int mid=1;
	for (int i=cnt-1;i>0;i--){
		if (a[i]){
			for (int j=0;j<=cnt/2-mid;j++) res+=dp[i-1][j];

			mid++;
		}
		
	}
	mid=0;
	for (int i=1;i<=cnt;i++){
		if (a[i]==1) mid++;
	}
	if (cnt/2>=mid) res++;
	return res;
	
	
}


int main(){
	init();
	cin>>l>>r;
	cout<<dp1(r)-dp1(l-1)<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值