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;
}