Description
给你一个 $n ^ 2$ 位的数 $k$ ,请你求出有多少个整数 $x \in [1, k]$ ,满足 $x$ 翻转或大于 $k$ 或翻转后大于等于它自己。 例如 123 翻转后为 321 。
Solution
对于这类问题,我们考虑使用 数位 DP  来解决。
正难则反,考虑求出翻转后小于等于 $k$ , 小于 它自己的数的个数。
所以如果设 $f(i)$ 表示 $i$ 翻转后的结果,那么答案 $ans=$
于是我们可以想到设 $f(i, p=0/1, q=0/1)$ 表示当前做到第 $i$ 位, $p$ 表示当前 小于/等于 $k$ 的前 $i$ 位,$q$ 表示将前 $i$ 位翻转后得到的后 $i$ 位 小于等于/大于 $k$ 的后 $i$ 位。
于是我们就得到了一个时间复杂度为 $O(n ^ 2)$ 的做法,具体细节见代码部分。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
   | #include <cstdio> #define maxN 1000010 #define mod 1000000007 long long f[maxN][2][2], a[maxN]; int main () { 	long long ans = 0, n = 0; 	scanf("%lld", &n); 	n *= n; 	for(long long i = 1;i <= n; i++) 	{ 		scanf("%1lld", &a[i]); 		ans = ans * 10 + a[i]; 		ans %= mod; 	} 	f[0][1][0] = 1; 	for(long long i = 0;i <= n - 1; i++) 	{ 		for(long long p = 0;p <= 1; p++) 		{ 			for(long long q = 0;q <= 1; q++) 			{ 				for(long long k = 0;k <= 9; k++) 				{ 					if(p && k > a[i + 1]) 					{ 						break; 					} 					long long pp = 0, qq = 0; 					if(p) 					{ 						if(k == a[i + 1]) 						{ 							pp = 1; 						} 					} 					if(!q) 					{ 						if(k > a[n - i]) 						{ 							qq = 1; 						} 					} 					else 					{ 						if(k >= a[n - i]) 						{ 							qq = 1; 						} 					} 					f[i + 1][pp][qq] += f[i][p][q]; 					f[i + 1][pp][qq] %= mod; 				} 			} 		} 	} 	long long da1 = (f[n][0][0] + f[n][1][0]) % mod; 	long long da2 = ((f[n / 2][0][0] + f[n / 2][0][1]) % mod + f[n / 2][1][0]) % mod; 	ans = (ans + mod - ((da1 + mod - da2) % mod * 500000004LL % mod)) % mod; 	printf("%lld", ans); 	return 0; }
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
   | #include <cstdio> #define maxN 1000010 #define mod 1000000007 long long f[maxN][2][2], a[maxN]; int main () { 	long long ans = 0, n = 0; 	scanf("%lld", &n); 	for(long long i = 1;i <= n * n; i++) 	{ 		scanf("%1lld", &a[i]); 		(ans = ans * 10 + a[i]) %= mod; 	} 	f[0][1][0] = 1; 	for(long long i = 0;i < n * n; i++) 	{ 		for(long long p = 0;p <= 1; p++) 		{ 			for(long long q = 0;q <= 1; q++) 			{ 				for(long long k = 0;k <= 9; k++) 				{ 					if(!(p & (k > a[i + 1]))) 					{ 						(f[i + 1][p & (k == a[i + 1])][((!q) & (k > a[n * n - i])) | (q & (k >= a[n * n - i]))] += f[i][p][q]) %= mod; 					} 				} 			} 		} 	} 	ans = (ans + mod - (((f[n * n][0][0] + f[n * n][1][0]) % mod + mod - ((f[n * n / 2][0][0] + f[n * n / 2][0][1]) % mod + f[n * n / 2][1][0]) % mod) % mod * 500000004LL % mod)) % mod; 	printf("%lld", ans); 	return 0; }
   |