数位dp

数位dp

P2657 [SCOI2009] windy 数

题目大意:

不含前导零且相邻两个数字之差至少为 \(2\) 的正整数被称为 windy 数。windy 想知道,在 \(a\)\(b\) 之间,包括 \(a\)\(b\) ,总共有多少个 windy 数?
\(a,b \le 2\times 10^9\)

思路:

\(f[i][j]\)表示一个\(i\)位数,最高位为\(j\),包括的windy数。例如\(f[3][6]\)统计的是\(600~699\)的答案。
统计时依次统计,要注意一些细节。

核心代码:

void init(){
	for(long long i=0;i<=9;i++)f[1][i]=1;
	
	for(long long i=2;i<=10;i++){
		for(long long j=0;j<=9;j++){
			for(long long w=0;w<=9;w++){
				if(abs(j-w)<2)continue;
				f[i][j]+=f[i-1][w];
			}
		}
	}
}

long long dp(long long x){
	if(!x)return 0;
	
	long long res=0,ws[15]={0},tot=0,xx=x;
	while(xx>0){
		ws[++tot]=xx%10;
		xx/=10;
	}
	
	bool ok=1;
	ws[tot+1]=999;
	for(long long i=tot;i>=1;i--){
		for(long long j=1;j<=9;j++)res+=f[i-1][j];  // 如果第i位是前导0,记录i-1位的答案
		if(ok)
			for(long long j=0;j<ws[i];j++)
				if((i!=tot||j!=0)&&abs(ws[i+1]-j)>=2)
					res+=f[i][j];
		if(abs(ws[i]-ws[i+1])<=1)ok=0;  // 此处不能break,例如123,需要统计0-9,10-99的答案 
	}
	long long last=999;
	ok=1;
	while(x>0){
		if(abs(x%10-last)<=1){
			ok=0; break;
		}
		last=x%10; x/=10;
	}
	res+=ok;
	return res;
}

P2602 [ZJOI2010]数字计数

题目大意:

给定两个正整数 \(a\) 和 bbb,求在 \(\[a,b\]\) 中的所有整数中,每个数码(digit)各出现了多少次。
\(a,b \le 10^12\)

思路:

直接统计即可,要明白\(f[i][j]\)的意义,\(f[3][6]\)表示\(6000-6999\),不是\(1-6999\)

核心代码:

void init(){
	for(LL i=0;i<=9;i++)f[1][i].c[i]=1;
	for(LL i=2;i<=12;i++){
		for(LL j=0;j<=9;j++){
			for(LL w=0;w<=9;w++)
				f[i][0].c[w]+=f[i-1][j].c[w];
		}
		for(LL j=1;j<=9;j++){
			f[i][j].c[0]=f[i][0].c[0];
			for(LL w=1;w<=9;w++)
				f[i][j].c[w]=f[i][0].c[w]+(LL)(j==w)*(t10[i-1]);
		}
		f[i][0].c[0]+=t10[i-1];
	}
}

qwe dp(LL x){
	// special
	if(x==0){
		qwe c;
		for(LL i=0;i<=9;i++)c.c[i]=0;
		c.c[0]=1;
		return c;
	}
	
	// translate x
	LL ws[15],tot=0,xx=x;
	while(x>0){
		ws[++tot]=x%10;
		x/=10;
	}
	
	qwe res;
	//clear
	for(LL i=0;i<=9;i++)res.c[i]=0;
	
	for(LL i=tot;i>=1;i--){
		if(ws[i]>=1){
			for(int j=0;j<ws[i];j++){
				res=res+f[i][j];
				if(i==tot&&j==0){
					for(int w=i-1;w>=1;w--)
						res.c[0]-=t10[w];
				}
			}
		}
		res.c[ws[i]]+=(xx%t10[i-1]+1);  // 别忘了给这一位自己统计上
	}
	return res;
}

posted @ 2022-03-03 18:11  Charisk_FOD  阅读(31)  评论(0)    收藏  举报