codeforces #326 D. Duff in Beach (dp)

题目:http://codeforces.com/problemset/problem/588/D

题意:已知长度为n的数组a[0...n-1]和长度为l的数组b[0...l-1],并且b[i]=a[i%n],在b[0...l-1]中找有多少种特殊的序列其满足3个条件:

Duff is so curious, she wants to know the number of subsequences of b like bi1, bi2, ..., bix (0 ≤ i1 < i2 < ... < ix < l), such that:

  • 1 ≤ x ≤ k
  • For each 1 ≤ j ≤ x - 1
  • For each 1 ≤ j ≤ x - 1bij ≤ bij + 1. i.e this subsequence is non-decreasing.

分析:记ss[i]为长度为i-1的方案数(从第一层开始的,即第一个元素的位置<n)。会用到的b[0...l-1]里面的元素最多有n*k个,将这些元素取出来,并标记位置,然后从小到大排序。那么枚举这n*k个元素,如果当前元素的标记的位置为id,那么以这个元素结尾的方案数为ss[id/n-1],因为已经排好序,上一层的方案对这个元素都是合法的,然后更新ss[id/n]。如果id<l,那么以当前元素结尾的方案数都可行,和当前序列类似的序列还有[l-(id+1)]/n个,加上去就行了。

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
const LL INF = (1ll<<31);
const LL mod = 1000000007;
const int maxn = 1E6+7;
pair <int ,int > p[maxn];
int a[maxn];
LL dp,sum[maxn];

int main()
{
	LL n,l,k,i,lim,id;
	scanf("%lld%lld%lld",&n,&l,&k);
	for(i=0;i<n;i++)
		scanf("%d",&a[i]);
	lim=n*k;
	for(i=0;i<lim;i++)
		p[i]=make_pair(a[i%n],i);
	sort(p,p+lim);
	LL ans=0;
	for(i=0;i<lim;i++)
	{
		id=p[i].second;
		if(id<n)
			dp=1;
		else
			dp=sum[id/n-1];
		sum[id/n]=(sum[id/n]+dp)%mod;
		if(id<l)
		{
			LL nums=(l-id+n-1)/n;
			ans=(ans+nums%mod*dp)%mod;
		}	
	}
	printf("%lld\n",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值