AT_arc148_e ≥ K
一种很新的思路。
考虑使得你放一个数的时候,要不然就是之后所有数都可以放在它旁边,要不然就是都不可以。
于是先排序,对于一个 \(<\dfrac{k}{2}\) 的数 \(a_i\),挂在第一个 \(\geq k-a_i\) 的位置上(本质或许是双指针,但我并不想这么说)。
然后从大到小放所有 \(\geq\dfrac{k}{2}\) 的数,放完一个数就把挂在它上面的数也放了,发现这样所有 \(\geq\dfrac{k}{2}\) 的数和 \(<\dfrac{k}{2}\) 的数分别满足最开始说的两种情况。
这样两种数放完以后会分别使得能放数的位置加一或减一,直接乘起来就完了。
最后除以每种数出现次数的阶乘来消去相同数的重复排列。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;
const int MAXN=2e5+10,mod=998244353;
int n,k,a[MAXN],cnt[MAXN];ll ans=1,T=1,P=1;
inline int ksm(ll a,int b=mod-2)
{
ll ans=1;
for(;b;b>>=1,a=a*a%mod)
if(b&1) ans=ans*a%mod;
return ans;
}
int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(0);
cin>>n>>k;
for(int i=1;i<=n;++i) cin>>a[i];
sort(a+1,a+1+n);
for(int i=1;i<=n&&a[i]<=(k-1)/2;++i)
{
if(a[n]+a[i]<k) cout<<"0\n",exit(0);
++cnt[lower_bound(a+1,a+n+1,k-a[i])-a];
}
for(int i=n;i&&a[i]>(k-1)/2;--i)
{
ans=ans*T%mod,++T;
for(int j=1;j<=cnt[i];++j)
ans=ans*T%mod,--T;
}
for(int i=1,j=1;i<=n;i=j)
{
while(a[j]==a[i]) ++j;
for(int k=1;k<=j-i;++k)
P=P*k%mod;
}
cout<<ans*ksm(P)%mod<<'\n';return 0;
}