由于今天队友太猛,我爆零了,赛后也才只补出一个题,所以就只写一个题解。
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));
}