[CF285E] Positions in Permutations

\(\text{Problem}:\)Positions in Permutations

\(\text{Solution}:\)

\(f_{i}\) 表示完美数恰好为 \(i\) 的排列数,\(g_{i}\) 表示钦定完美数为 \(i\) 的排列数,由二项式反演,有:

\[f_{i}=\sum\limits_{j=i}^{n}(-1)^{j-i}\binom{j}{i}g_{j} \]

现在考虑求出 \(g\)。设 \(h_{i,j,0/1,0/1}\) 表示前 \(i\) 个位置有 \(j\) 个完美数,\(i\) 选/不选,\(i+1\) 选/不选的方案数,有转移:

  • \(i=1\),边界条件 \(h_{1,0,0,0}=h_{1,1,0,1}=1\)
  • \(i=n\),去掉有关 \(i+1\) 的转移即可。
  • \(1<i<n\),且 \(i\) 不是完美数,有:

\[h_{i-1,j,0,0}+h_{i-1,j,1,0}\rightarrow h_{i,j,0,0}\\ h_{i-1,j,0,1}+h_{i-1,j,1,1}\rightarrow h_{i,j,1,0} \]

  • \(1<i<n\),且 \(i\) 是完美数,有:

\[h_{i-1,j-1,0,0}\rightarrow h_{i,j,0,0}\\ h_{i-1,j-1,0,1}\rightarrow h_{i,j,1,0}\\ h_{i-1,j-1,0,0}+h_{i-1,j-1,1,0}\rightarrow h_{i,j,0,1}\\ h_{i-1,j-1,0,1}+h_{i-1,j-1,1,1}\rightarrow h_{i,j,1,1} \]

显然 \(g_{j}=h_{n,j,0,0}+h_{n,j,1,0}\),故可以求出 \(f_{i}\),总时间复杂度 \(O(nm)\)

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=1010, Mod=1e9+7;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,m,h[N][N][2][2],g[N],fac[N+5],inv[N+5];
inline int ksc(int x,int p) { int res=1; for(;p;p>>=1, x=x*x%Mod) if(p&1) res=res*x%Mod; return res; }
inline int C(int x,int y) { if(x<y||x<0||y<0) return 0; return fac[x]*inv[x-y]%Mod*inv[y]%Mod; }
signed main()
{
	fac[0]=1;
	for(ri int i=1;i<=N;i++) fac[i]=fac[i-1]*i%Mod;
	inv[N]=ksc(fac[N],Mod-2);
	for(ri int i=N;i;i--) inv[i-1]=inv[i]*i%Mod;
	n=read(), m=read();
	h[1][0][0][0]=h[1][1][0][1]=1;
	for(ri int i=2;i<=n;i++)
	{
		for(ri int j=0;j<=i;j++)
		{
			h[i][j][0][0]=(h[i][j][0][0]+h[i-1][j][0][0]+h[i-1][j][1][0])%Mod;
			h[i][j][1][0]=(h[i][j][1][0]+h[i-1][j][0][1]+h[i-1][j][1][1])%Mod;
			if(!j) continue;
			h[i][j][0][0]=(h[i][j][0][0]+h[i-1][j-1][0][0])%Mod;
			h[i][j][1][0]=(h[i][j][1][0]+h[i-1][j-1][0][1])%Mod;
			if(i<n)
			{
				h[i][j][0][1]=(h[i][j][0][1]+h[i-1][j-1][0][0]+h[i-1][j-1][1][0])%Mod;
				h[i][j][1][1]=(h[i][j][1][1]+h[i-1][j-1][0][1]+h[i-1][j-1][1][1])%Mod;
			}
		}
	}
	for(ri int i=0;i<=n;i++) g[i]=fac[n-i]*(h[n][i][0][0]+h[n][i][1][0])%Mod;
	int ans=0;
	for(ri int i=m;i<=n;i++)
	{
		int w=C(i,m)*g[i]%Mod;
		if((i-m)&1) ans=(ans-w+Mod)%Mod;
		else ans=(ans+w)%Mod;
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2021-04-25 20:09  zkdxl  阅读(55)  评论(0编辑  收藏  举报