题解:P14639 【OIMO Round 1】世界线
Freezyfish · · 题解
很好的组合数学让我的大脑旋转。
出题人建议评黄?
思路
发现一个重要性质:把序列排序成为序列
如果是一个排列,那么就很简单:答案是
序列怎么做?你发现如果选得只剩一种数了,那么她就只有一种选法了,你就枚举最后这个数是谁即可。你钦定最后第一次到达只有一种数的状态时,这个数还有多少个,那么上一个选的数就不能是这个数。
排列组合计算。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read()
{
int t=1,x=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') t=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return t*x;
}
const int N=1e6+15,mod=998244353;
int p[N];
int n;
int qp[N];
int ans=0;
int qmi(int a,int b)
{
int res=1;
while(b)
{
if(b&1)res=(res*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return res;
}
inline int C(int a,int b)
{
if(a<b)return 0;
return qp[a]*qmi(qp[b],mod-2)%mod*qmi(qp[a-b],mod-2)%mod;
}
signed main()
{
n=read();
qp[0]=1;
for(int i=1;i<=n;i++)p[i]=read(),qp[i]=qp[i-1]*i%mod;
sort(p+1,p+1+n);
int l=1;
for(int i=1;i<=n;)
{
l=i;
while(p[l+1]==p[i])l++;
ans=(ans+C(i-1+n-l,i-1))%mod;
for(int j=1;j<=l-i;j++)
{
ans=(ans+C(j+i-1+n-l-1,j+i-1)%mod)%mod;
//cout<<ans<<"\n";
ans=(ans+C(i-1+n-l+j-1,n-l+j)%mod)%mod;
//cout<<i-1+n-l+j-1<<" "<<n-l+j<<"\n";
}
//cout<<ans<<"\n";
i=l+1;
}
printf("%lld\n",ans);
return 0;
}