7-23 翻转车牌 (10分)
有一个奇数位(如5位)的车牌号,由基本数字(0~9)组成,问有多少车牌翻转180度后号码还是原来的车牌并且各位数字之和能被3整除。(csp-s2019初试题)
输入格式:
一个数字:n(<10),表示车牌号位数
输出格式:
输出所有满足要求的车牌号码(按字典序排列,每行一个号码),最后一行是满足要求的车牌号总数。
输入样例:
3
输出样例:
000
111
609
888
906
5
当有一半的数字确定后,可以翻转确定另一半数字。所以操作次数只有m=n/2+0.5次(+0.5完成奇偶的四舍五入)。观察数字可知(0,1,8)三个数翻转后还是本身,(6,9)可以相互变换。
例如:
- 当n=3时,操作次数应该是两次(a3由a1得到)
- 当n=4时操作次数也是两次(a4由a1得到, a3由a2得到)
另外,仅有奇数位数的车牌中心位限制在(0,1,8)三个数里。
例如:
- 三位车牌(X_X’ ),则下划线处不能填(6,9),仅在(0,1,8)里选择
- 四位车牌(X_ _X’),则下划线可以在(0,1,6,8,9)里选择变换
#include<bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for(int i = l; i <= r; i++)
#define rep1(i, l, r) for(int i = l; i < r; i++)
int n, m; // 输入 操作次数
int x[15], sum = 0; // 当前车牌 当前车牌数字和
int ans = 0; //总共符合要求的车牌数目
int b[3] = {0, 1, 8}; // 变为自身的数
int c[2][5] = {0, 1, 6, 8, 9,
0, 1, 9, 8, 6}; //可以相互转换的数
int dfs(int t){
if(t > m){ //操作次数到了之后输出并计数
if(sum % 3 == 0){
for(int i = 1; i <= n; i++) cout << x[i];
cout << endl;
ans++;
}
}
else{
if(t != n - t + 1){ //可以自由选择
for(int i = 0; i < 5; i++){
x[t] = c[0][i];
x[n - t + 1] = c[1][i];
sum += (c[0][i] + c[1][i]);
dfs(t + 1);
sum -= (c[0][i] + c[1][i]);
}
}
else{ //奇数中心位必须是从0,1,8中选择
for(int i = 0; i < 3; i++){
x[t] = b[i];
sum += b[i];
dfs(t + 1);
sum -= b[i];
}
}
}
}
int main(){
cin >> n;
m = n * 1.0 / 2 + 0.5; //计算操作次数
dfs(1);
cout << ans << endl;
return 0;
}