cf2 B. The least round way
题意:
在给定整数矩阵上从左上走到右下,每次只能往右或往下走一步,最小化路径上所有数的乘积的末尾0的数量。要输出路径
\(n\le 1000,0\le a_i\le 1e9\)
思路:
一个整数末尾0的数量就是它的质因子分解式中2的指数和5的指数的最小值。
2和5是独立的,反正找最小的就行了
矩阵中有0怎么办?如果一条路径经过0,那么其乘积是0,末尾有一个0。所以最好能不经过0且得到一个末尾无0的答案,否则任取一条经过0的路径即可
const signed N = 3 + 1000;
int n, zero, f[N][N][2]; //2,5
void pri(int i, int j, int k) {
if(i == 1 && j == 1) return;
if(f[i-1][j][k] < f[i][j-1][k]) pri(i-1,j,k), cout << 'D';
else pri(i,j-1,k), cout << 'R';
}
void sol() {
cin >> n;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
int x; cin >> x;
if(x == 0) zero = i, x = 10;
while(x % 2 == 0) x /= 2, f[i][j][0]++;
while(x % 5 == 0) x /= 5, f[i][j][1]++;
}
//不能从边界外转移
for(int i = 1; i <= n; i++)
f[i][0][0] = f[i][0][1] = f[0][i][0] = f[0][i][1] = INF;
//dp
for(int t = 0; t <= 1; t++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) if(i > 1 || j > 1)
f[i][j][t] += min(f[i-1][j][t], f[i][j-1][t]);
//输出答案
int k = f[n][n][0] < f[n][n][1] ? 0 : 1;
if(zero && f[n][n][k]) { //有0且答案经过0
cout << 1 << endl;
for(int i = 1; i < zero; i++) cout << 'D';
for(int j = 1; j < n; j++) cout << 'R';
for(int i = zero; i < n; i++) cout << 'D';
}
else cout << f[n][n][k] << endl, pri(n, n, k);
}

浙公网安备 33010602011771号