2018 Benelux Algorithm Programming Contest (BAPC 18) 题解 寒假自训第五场

由于今天队友太猛,我爆零了,赛后也才只补出一个题,所以就只写一个题解。

E. Entirely Unsorted Sequences

题意:在一个序列中,定义一个元素 ai 是有序的:ai左边的数都<=ai,ai右边的数都>=ai,定义一个序列是完全无序的:序列中所有元素都是无序元素。给一个序列,你可以任意排列,排列后求有多少种不同完全无序数组。

如果正过来写,很麻烦,我们反过来,求出有多少个序列,其中至少有一个有序元素,然后总排列数减之就是答案,这么求呢?

我举个例子:排序后的序列:1 1 1 2 2 2,设d[i]为前 i 个元素可以组成无序数组的个数,p[i]为后面 i 个元素的排列数,我们分别计算每个数是有序元素时的贡献,第一个数1的贡献很明显是这种情况:1排第一位,重点:我们知道有序元素左边都<=它,右边都>=它,所以后面五个元素任意排列,贡献:5!/2!/3!,然后接下来我们计算2在第4位的贡献(为啥不算1在第2、3位的贡献?因为冗余了),很明显贡献是d[3]*p[2],为啥牵扯到d数组了,因为当前3个数的子序列是非完全无序时,已经计算过前面3个元素贡献和第4个元素的贡献了,所以此时前三个数应该要完全无序,同理第5个2贡献是d[4]*p[1],第6个2贡献是d[5],答案d[6]=p[1]-上面这些数和。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5005,mod=1e9+9;
ll p[maxn],inv[maxn],a[maxn],ans[maxn];
ll ksm(ll x, ll y)
{
	ll res=1;
	while(y)
	{
		if(y&1)res=res*x%mod;
		x=x*x%mod;
		y/=2;
	}
	return res;
}
void add(ll& x,ll y)
{
	x=(x+y+mod)%mod;
}
void init()
{
	p[0]=inv[0]=1;
	for(int i=1;i<maxn;i++)
	p[i]=p[i-1]*i%mod,inv[i]=ksm(p[i],mod-2);
}
ll dfs(int x)
{
	if(a[1]==a[x])return 0;
	if(ans[x])return ans[x];
	ll sum=0,tt=1;
	for(int i=x;i;i--)
	{
		if(a[i]!=a[1])
		{
			int j=1;
			while(a[i]==a[i-1])
			{
				add(sum,dfs(i-1)*p[x-i]%mod*tt%mod*inv[j-1]%mod);
				j++,i--;	
			}
			add(sum,dfs(i-1)*p[x-i]%mod*tt%mod*inv[j-1]%mod);
			tt=tt*inv[j]%mod;
		}
		else
		{
			add(sum,p[x-1]*tt%mod*inv[i-1]%mod);
			tt=tt*inv[i]%mod;	
			break;
		}
	}
	ans[x]=(p[x]*tt%mod-sum+mod)%mod;
	return ans[x];
}
int main()
{
	init();
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
	sort(a+1,a+1+n);
	printf("%lld\n",dfs(n));
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙橘子猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值