1. 程式人生 > 實用技巧 >HDU6794 Tokitsukaze and Multiple(字首和/貪心/尺取法)

HDU6794 Tokitsukaze and Multiple(字首和/貪心/尺取法)

Tokitsukaze has a sequence of length n, denoted by a

.

Tokitsukaze can merge two consecutive elements of a

as many times as she wants. After each operation, a new element that equals to the sum of the two old elements will replace them, and thus the length of a will be reduced by 1

.

Tokitsukaze wants to know the maximum possible number of elements that are multiples of p

she can get after doing some operations (or doing nothing) on the sequence a

.

Input

There are several test cases.

The first line contains an integer T (1≤T≤20), denoting the number of test cases. Then follow all the test cases.

For each test case, the first line contains two integers n and p(1≤n,p≤105), denoting the length of the sequence and the special number, respectively.

The second line contains n integers, where the i-th integer \(a_i\)(1≤\(a_i\)≤105) is the i-th element ofa

.

It is guaranteed that the sum of n in all test cases is no larger than \(10^6\)

.

Output

For each test case, output in one line the maximum possible number of elements that are multiples of p after doing some operations.

Sample Input

2
5 3
2 1 3 2 1
3 1
123 456 789

Sample Output

3
3

啊我好菜我好菜我好菜Q^Q

放一道和這個題很類似的https://codeforces.com/problemset/problem/1333/C

題意就是求最大的不相交的和為p的倍數的連續子段的數目。

注意到這樣一個性質:對這個數列求字首和再取模,如果有兩個位置的數相等,說明這段區間的和是p的倍數。因此可以求出當前位置取模過後的字首和的值,如果這個值在map裡出現過,就更新ans++,同時清空map並把當前字首和的值設定為0(因為當前點到之前的點之間有線段覆蓋的話,後面的點和之前的點之間就不能有線段了)再新增map[0]=1(別忘了取模後為0的情況);沒有出現過的話就把當前取模過後的字首和的值新增到map裡。

貌似還有DP做法:

last[i]陣列記錄最後i出現的位置 dp[i]=max(dp[i-1],dp[last[cur]]+1);

#include <bits/stdc++.h>
using namespace std;
int n, p, ans;
int sum[100005] = {0};
int main()
{
	int t;
	cin >> t;
	while(t--)
	{
		ans = 0;
		map<int, int> mp;
		scanf("%d%d", &n, &p);
		mp[0] = 1;
		for(int i = 1; i <= n; i++)
		{
			int temp;
			scanf("%d", &temp);
			sum[i] = (sum[i - 1] + temp) % p;
			if(mp.count(sum[i]))
			{
				ans++;
				mp.clear();
				sum[i] = 0;
				mp[0] = 1;
			}
			else
			{
				mp[sum[i]] = 1;
			}
		}
		cout << ans << endl;
	}
}