选拔赛之dp

来源:互联网 发布:淘宝买家秀怎么发微淘 编辑:程序博客网 时间:2024/04/30 21:24

第102题: 小P 的问题课堂2

大概能看的出是dp,但是自己不会写转移方程


而且就算会了也不会优化,,

多学的东西:

1:hash前要去重,2:这里原本的复杂度是超的,所以用了f和tot来记录重复计算的东西。。。很巧妙。。3:hash的方式用这种函数的方式更好。


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <map>#include <string>#include <queue>#include <cmath>#include <tr1/unordered_map>#include <bits/stdc++.h>using namespace std;using namespace std::tr1;#define N 20010#define M 1000010#define LL long long#define ULL unsigned long long #define eps 1e-8#define pii pair<int, int>#define pdd pair<double, double>#define MP make_pair#define pb push_back#define inf 0x3f3f3f3f#define fi first#define se second#define md (ll+rr>>1)#define lson ll, md#define rson md+1, rr#define mod 1000000007int a[N];int dp[N][110];int f[N][110];int tot[110];LL sum[N], san[N];int cnt;void RE() {vector<int> v;v[0] = -1;}int hx(int LL x) {return lower_bound(san, san+cnt, x) - san;}int main() {int T;scanf("%d", &T);while(T--) {int n, k;scanf("%d%d", &n, &k);if(k > n) RE();cnt = 0;for(int i = 1; i <= n; ++i) {scanf("%d", &a[i]);sum[i] = sum[i-1] + a[i];san[cnt++] = sum[i];}san[cnt++] = 0;sort(san, san+cnt);cnt = unique(san, san+cnt) - san;for(int i = 1; i <= n; ++i) sum[i] = hx(sum[i]);memset(dp, 0, sizeof dp);memset(f, 0, sizeof f);memset(tot, 0, sizeof tot);dp[0][0] = 1;f[hx(0)][0] = 1;tot[0] = 1;for(int i = 1; i <= n; ++i) {for(int j = 1; j <= min(k, i); ++j) {dp[i][j] += tot[j-1] - f[sum[i]][j-1] + mod;dp[i][j] %= mod;}for(int j = 1; j <= min(k, i); ++j) {f[sum[i]][j] += dp[i][j];tot[j] += dp[i][j];f[sum[i]][j] %= mod;tot[j] %= mod;}}printf("%d\n",dp[n][k]);}}

0 0
原创粉丝点击