Comet OJ - Contest #3 子序列子序列子序列...
题目链接:点我啊╭(╯^╰)╮
题目大意:
解题思路:
对于子序列 是完美序列,那么 是 的倍数
设 , 为奇数,则分类讨论如下:
若 ,则 表示长度为 的序列,求和后对 取模得k的子序列个数
若 ,则 表示长度至少为 的序列,求和后对 取模得 的子序列个数
对于子序列是否包含 ,递推求出 ~ 的所有情况
最后复杂度为
核心:dp的优化
#include<bits/stdc++.h>
#define rint register short int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const ll mod = 1e9 + 7;
const int maxn = 5e3 + 10;
int a[maxn], b[maxn], dp[15][maxn];
int main() {
int n, m;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++) scanf("%d", a+i);
int c = 0, ans = 0;
for(int i=m; i%2==0; i/=2, c++);
for(rint t=1; t<=c+1; t++) { // 枚举前 c位
memset(dp,0,sizeof(dp));
int d = m / (1 << t-1);
dp[0][0] = 1;
for(rint i=1; i<=n; i++) { // 逐个插入 a[i]
for(rint k=0; k<d; k++) b[k] = dp[c+1][k];
for(rint j=t-1; j>=0; j--) {
for(rint k=0; k<d; k++) {
dp[j+1][(k+a[i])%d] += dp[j][k];
dp[j+1][(k+a[i])%d] %= mod;
}
}
if(t==c+1) // t > c 的情况
for(rint k=0; k<d; k++) {
dp[c+1][(k+a[i])%d] += b[k];
dp[c+1][(k+a[i])%d] %= mod;
}
}
ans += dp[t][0];
ans %= mod;
}
printf("%d\n", ans);
}