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);
}
posted @ 2022-06-15 12:56  Bellala  阅读(27)  评论(0)    收藏  举报