1004 Tokitsukaze and Multiple
题意:给定序列
a
n
a_n
an,数字
p
p
p。需要把数列分段,问段内和是p的倍数的最大个数。
思路:题意就已经换了一下了,原题这样:
问题就转换成了数列分段,有dp味道了。因为题目要求连续。8错8错,前缀和来了。
- 用dp记录当前位置 i i i的最大个数,问题就在从啥状态转移来?好像可以随便转移,但是有贡献的位置 j j j必然是 ∑ k = j i a i % p = 0 \sum_{k=j}^i a_i\%p=0 ∑k=jiai%p=0的地方。
- 现在剩下的问题就是要找这个位置 j j j,利用前缀数组 % p \%p %p s u m sum sum记录,如果发现当前位置 s u m i sum_i sumi存在了一些位置相等,说明从这些位置转移来的 d p + + dp++ dp++.
- 当然,如果不存在以上的位置就直接 d p i = d p i − 1 dp_i=dp_{i-1} dpi=dpi−1就好
上号!
int n;
LL a[maxn], sum[maxn], dp[maxn];
int mp[maxn];
int main() {
int T;
int n;
LL p;
sci(T);
while (T--)
{
sum[0] = 0;
dp[0] = 0;
sci(n); scl(p);
for (int i = 0; i <= p; i++)mp[i] = -1;
mp[0] = 0;
for (int i = 1; i <= n; i++) {
scl(a[i]);
sum[i] = (a[i] + sum[i - 1]) % p;
if (mp[sum[i]] != -1)dp[i] = max(dp[i-1], dp[mp[sum[i]]] + 1);
else dp[i] = dp[i - 1];
mp[sum[i]] = i;
}
cout << dp[n] << endl;
}
return 0;
}