小红删数字

[题目链接](https://www.nowcoder.com/practice/1287555d90d34de3be4ae338b18c1fbd)

思路

每次操作取数组最后两个数 ,删除后将 放回末尾。操作 次后只剩一个数。问最终结果为 的方案数各是多少。

关键观察

由于每次操作的结果都取个位数,后续运算也只关心个位数,因此整个过程只和每个数的个位有关。

操作顺序是固定的:每次取最后两个元素,所以第一次操作一定是合并 ,第二次是合并结果与 ,以此类推。合并的顺序从右往左是确定的,每步只有加法或乘法两种选择。

DP 定义

表示当前从右侧已处理的元素合并后,结果个位为 的方案数。

初始状态

转移:从 ,对每个当前个位 ,可以通过加法得到 ,或通过乘法得到 ,其中

$$

$$

特判

时没有操作,剩余数字就是 本身。若 ,则对应位置方案数为 ;否则所有位置均为

复杂度

  • 时间复杂度,每个元素对 10 个可能的个位进行转移。
  • 空间复杂度,只需维护长度为 10 的 DP 数组。

代码

#include <bits/stdc++.h>
using namespace std;

const int MOD = 1e9 + 7;

int main() {
    int n;
    scanf("%d", &n);
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }

    if (n == 1) {
        for (int i = 0; i < 10; i++) {
            printf("%d%c", a[0] == i ? 1 : 0, i == 9 ? '\n' : ' ');
        }
        return 0;
    }

    vector<long long> dp(10, 0);
    dp[a[n - 1] % 10] = 1;

    for (int i = n - 2; i >= 0; i--) {
        vector<long long> ndp(10, 0);
        int v = a[i] % 10;
        for (int d = 0; d < 10; d++) {
            if (dp[d] == 0) continue;
            ndp[(v + d) % 10] = (ndp[(v + d) % 10] + dp[d]) % MOD;
            ndp[(v * d) % 10] = (ndp[(v * d) % 10] + dp[d]) % MOD;
        }
        dp = ndp;
    }

    for (int i = 0; i < 10; i++) {
        printf("%lld%c", dp[i], i == 9 ? '\n' : ' ');
    }
    return 0;
}
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }

        final int MOD = 1000000007;

        if (n == 1) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 10; i++) {
                if (i > 0) sb.append(' ');
                sb.append(a[0] == i ? 1 : 0);
            }
            System.out.println(sb.toString());
            return;
        }

        long[] dp = new long[10];
        dp[a[n - 1] % 10] = 1;

        for (int i = n - 2; i >= 0; i--) {
            long[] ndp = new long[10];
            int v = a[i] % 10;
            for (int d = 0; d < 10; d++) {
                if (dp[d] == 0) continue;
                ndp[(v + d) % 10] = (ndp[(v + d) % 10] + dp[d]) % MOD;
                ndp[(v * d) % 10] = (ndp[(v * d) % 10] + dp[d]) % MOD;
            }
            dp = ndp;
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            if (i > 0) sb.append(' ');
            sb.append(dp[i]);
        }
        System.out.println(sb.toString());
    }
}