A. 【普转提七联测 Day 6】石头

题目大意

小 A 非常喜欢素数。他收集了很多石头。

这些石头的特点是:重量都是正整数,并且都是素数。 他把石头排成了一排,一个个膜拜。突然,天上降下了落雷,正好击中了某些石头,使它们分成了多瓣。

幸运的是,石头的相对位置没有改变, 并且,新的石头的重量也都是整数。

小 A 希望将石头重新拼成全部都是素数的情况。请你计算一下,他可以还原出多少种不同的序列。注意,位 置不同算不同的序列,比如 (2, 3) 与 (3, 2) 是不同的。

Solution

我们不用考虑把每个序列拿出来,也不需要区间 DP。

线性 DP:\(f_i\)表示前 i 个数字,能组成的合法串数。

初始状态\(f_0 =1\),转移:

\[f_i = \sum_{j = 1}^i f_j[(s_i-s_{j - 1})为质数] \]

#include <bits/stdc++.h>
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define DOWN(i, a, b) for (int i = (a); i >= (b); --i)
const int N = 1e3 + 10, mod = 987654321, M = 1e6 + 10;
int n, a[N];
int pr[M], len = 0, v[M];

inline int add(int a, int b) { return a + b >= mod ? a + b - mod : a + b; }
inline int read() {
    int s = 0, w = 1;
    char c = getchar();
    while ((c < '0' || c > '9') && c != '-') c = getchar();
    if (c == '-') w = -1, c = getchar();
    while (c <= '9' && c >= '0')
        s = (s << 3) + (s << 1) + c - '0', c = getchar();
    return s * w;
}
template <class T>
inline void write(T x) {
    if (x < 0) x = ~x + 1, putchar('-');
    if (x > 9) write(x / 10);
    putchar(x % 10 + 48);
    return void();
}
int s[N], f[N];

inline void Pre() {
    v[1] = 1;
    FOR(i, 2, M - 10) {
        if (!v[i]) pr[++len] = i;
        FOR(j, 1, len) {
            if (pr[j] * i > M - 10) break;
            v[pr[j] * i] = pr[j];
            if (!(i % pr[j])) break;
        }
    }
}
signed main(void) {
    n = read();
    Pre();
    FOR(i, 1, n) a[i] = read(), s[i] = s[i - 1] + a[i];
    f[0] = 1;
    FOR(i, 1, n)
    FOR(j, 1, i) if (!v[s[i] - s[j - 1]]) f[i] = add(f[i], f[j - 1]);
    write(f[n]);
    putchar(10);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zqytcl/p/13205183.html