您的位置:首页 > 其它

Codeforces Round #326 (Div. 2) D. Duff in Beach(LIS)

2016-01-26 18:53 405 查看
题意:

给定一个长度为N的序列a,给定一个长度为L≤1018的序列b,且bi=ai%N

求长度不超过K的b的不降子序列的个数,这个LIS的每个元素不能在同一个N周期内

分析:

由于每个周期最多只能选择一个,将a序列排序

考虑dp[i][j]:=长度为i,且以有序序列a第j个结尾的LIS的个数

转移的时候我们可以维护一个指针,这样转移就是均摊O(1)的了

统计答案时,由于是连续周期的,假如可选周期是T,当前长度为i,那么应该乘上(T−i+1)

代码:

//
//  Created by TaoSama on 2016-01-26
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e6 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

typedef long long LL;
int n, K; LL l;
pair<int, int> a
;

int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);

while(scanf("%d%I64d%d", &n, &l, &K) == 3) {
for(int i = 0; i < n; ++i) {
scanf("%d", &a[i].first);
a[i].second = i;
}
sort(a, a + n);

vector<vector<int> > f(K, vector<int>(n));
for(int i = 0; i < n; ++i) f[0][i] = 1;
for(int i = 1; i < K; ++i) {
int sum = 0;
for(int j = 0, k = 0; j < n; ++j) {
while(k < n && a[k].first <= a[j].first)
sum = (sum + f[i - 1][k++]) % MOD;
f[i][j] = sum;
}
}
LL ans = 0;
for(int i = 0; i < K; ++i) {
for(int j = 0; j < n; ++j) {
LL cnt = l / n + (a[j].second < l % n);
if(cnt - i > 0) {
ans += (cnt - i) % MOD * f[i][j] % MOD;
ans %= MOD;
}
}
}
printf("%I64d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp LIS