洛谷P7158题解

思路

总体上看下来,这道题不能用爆搜( \(1\le n\le 10^5\) ),所以说,可行的方法就是 dp。又注意到,以任何一个数字为 \(k\) 都是等价的,所以说这道题的答案与 \(k\) 无关,接下来的问题就是转移方程了。

转移方程

我们建立两个数组 \(dp1\)\(dp2\) 我们用第一个数组存储在第 \(i\) 位上符合要求的数的个数,用第二个数组存储不符合要求的数目。而对于在 \(i+1\) 位上的所有数,我们可以理解为是在第 \(i\) 位的数后加入一个数字得到的,所以说 \(i+1\) 位上的符合要求的数必定是由第 \(i\) 位的符合要求的数与一个不为 \(k\) 的数字组成的所有数和在第 \(i\) 位上符合要求的数与 \(k\) 组成的,同理也可以得到 \(dp2\) 的转移方程。

\[\mathit{dp1}_{i}=\mathit{dp1}_{i-1}\times 9+\mathit{dp2}_{i-1} \]

\[\mathit{dp2}_{i}=\mathit{dp2}_{i-1}\times 9+\mathit{dp1}_{i-1} \]

同时在 \(n=1\) 时要注意特判,直接输出 \(9\)

接下来就是代码实现的过程了。(记得不要忘了取模)

Code

#include <stdio.h>
using namespace std;
int main(){
	int t;
	scanf("%d",&t);
	long long dp1[114519],dp2[114519];//数组必须要开的比n的最大值大
	dp1[1]=8,dp2[1]=1;
	for(int i=1;i<=114514;i++){//循环次数只要超过10的五次方即可
		dp1[i]+=dp2[i-1];
		dp1[i]+=dp1[i-1]*9;
		dp1[i]%=998244353;
		dp2[i]+=dp2[i-1]*9;
		dp2[i]+=dp1[i-1];
		dp2[i]%=998244353;
	}
	for(int i=1;i<=t;i++){
		int n,k;
		scanf("%d%d",&n,&k);
		if(n==1){
			printf("9\n");
			continue;
		}//特判
		printf("%d\n",dp1[n]);	
	}
	return 0;	
} 
posted @ 2022-11-09 23:27  nxhx  阅读(50)  评论(0)    收藏  举报
1 2 3
4