[Cometoj#3 C]子序列子序列子序列..._动态规划_数论

子序列子序列子序列...

题目链接:https://cometoj.com/contest/38/problem/C?problem_id=1542

数据范围:略。


题解:

神仙题,感觉这个题比$D$还难一些,$Orz$原题解。

http://static.eduzhixin.com/cometoj/solution/contest_38_1.pdf

代码:

#include <bits/stdc++.h>

#define N 5010 

#define M 21 

#define Pyd 1000000007 

using namespace std;

int a[N];

int dp[M][N];

int tmp[N];

int mod[M];

int n, m;

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
	int x = 0, f = 1;
	char c = nc();
	while (c < 48) {
		if (c == '-')
			f = -1;
		c = nc();
	}
	while (c > 47) {
		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
	}
	return x * f;
}

int main() {
	n = rd(), m = rd();
	for (int i = 1; i <= n; i ++ ) {
		a[i] = rd();
	}
	int k = 0;
	while (m % (1 << k) == 0) k ++ ;
	mod[0] = mod[1] = m;
	for (int i = 2; i <= k; i ++ ) mod[i] = mod[i - 1] / 2;
	dp[0][0] = 1;
	for (int i = 1; i <= n; i ++ ) {
		for (int j = 0; j < mod[k]; j ++ ) tmp[(j + a[i]) % mod[k]] = dp[k][j];
		for (int j = 0; j < mod[k]; j ++ ) {
			dp[k][j] += tmp[j];
			if (dp[k][j] >= Pyd) dp[k][j] -= Pyd;
		}
		for (int p = k - 1; p > 0; p -- ) {
			for (int j = 0; j < mod[p]; j ++ ) {
				int nj = (j + a[i]) % mod[p + 1];
				dp[p + 1][nj] += dp[p][j];
				if (dp[p + 1][nj] >= Pyd) dp[p + 1][nj] -= Pyd;
			}
		}
		dp[1][a[i]] ++ ;
		if (dp[1][a[i]] >= Pyd) dp[1][a[i]] -= Pyd;
	}
	int ans = 0;
	for (int i = 1; i <= k; i ++ ) {
		ans += dp[i][0];
		if (ans >= Pyd) ans -= Pyd;
	}
	
	cout << ans << endl ;
	return 0;
}

 

posted @ 2019-10-23 15:15  JZYshuraK_彧  阅读(166)  评论(0编辑  收藏  举报