P7967 [COCI2021-2022#2] Magneti 做题记录
P7967 [COCI2021-2022#2] Magneti
Description
给定 \(n\) 个磁铁和 \(m\) 个空位,其中相邻空位之间的距离为 \(1\),每个空位可放置一个磁铁。所有 \(n\) 个磁铁都必须被放置。每个磁铁可以吸引距离小于 \(r_i\) 的其它磁铁。
求所有磁铁互不吸引的方案总数对 \(10^9+7\) 取模的结果。
Solution
很难入手的一道题。因为我们发现,无论是以磁铁个数还是填的格子数为阶段,都无法合理地转移。
我们把整个过程强行拆为两步。首先我们先在板子下面将磁铁排列好,再将磁铁移动到板子上。
先将磁铁按照吸引半径从小到大排列。那么我在加入一个新磁铁时,只需要考虑当前磁铁会不会吸引其他的磁铁。
这样还是不好直接转移,因为不好处理在两个磁铁中再插入一个磁铁的情况。
问题出在,我在现在的决策中需要知道原先具体是哪些磁铁相邻,才能得出新状态中所需要占据的格子数量。
那么不妨在当前时刻就决定我的某两个磁铁要不要相邻,也就是决定我当前磁铁组成的连续段个数。
设 \(f_{i,j,l}\) 表示考虑到第 \(i\) 个磁铁,当前磁铁组成了 \(j\) 个连续段,总共需要占据 \(l\) 个格子的排列方案数。
我们有三种转移:
- 新磁铁单独成段,可以放在 \(j+1\) 个位置里,\(f_{i,j,l}\times(j+1)\rightarrow f_{i+1,j+1,l+1}\);
- 新磁铁与某一个连续段合并,与左右合并各有 \(j\) 个位置,\(f_{i,j,l}\times2j\rightarrow f_{i+1,j,l+r_{i+1}}\);
- 新磁铁把左右两边的段都合并起来,有 \(j-1\) 个位置,\(f_{i,j,k}\times (j-1)\rightarrow f_{i+1,j-1,k+2r_{i+1}-1}\)。
最后我们所有的磁铁都变为了一个连续段。
对于一个状态 \(f_{n,1,l}\),板子上还有 \(m-l\) 个空位。那么我现在就要求出 \(m-l\) 个空位被分为 \(n+1\) 个部分,每个部分可以为空的方案数。
问题转化为不定方程整数解个数问题,就得出答案的转移 \(f_{n,1,l}\times \binom{m-l+n}{n}\rightarrow ans\)。
int n,m,a[N];
ll f[N][N][M],fac[M+N+5],caf[N+M+5];
const ll mod=1e9+7;
inline ll Mod(ll x){return (x>=mod)?(x-mod):(x);}
inline void Add(ll &x,ll y){x=Mod(x+y);}
ll QuickPow(ll x,ll y){
ll res=1;
while(y){
if(y&1) res=res*x%mod;
x=x*x%mod; y>>=1;
}
return res;
}
void FacInit(){
fac[0]=caf[0]=1;
for(int i=1;i<=m+n+5;i++) fac[i]=fac[i-1]*i%mod;
caf[m+n+5]=QuickPow(fac[n+m+5],mod-2);
for(int i=n+m+4;i;i--) caf[i]=caf[i+1]*(i+1)%mod;
}
ll C(int x,int y){
if(x<0||y<0||x<y) return 0;
return fac[x]*caf[y]%mod*caf[x-y]%mod;
}
signed main(){
read(n),read(m);
for(int i=1;i<=n;i++) read(a[i]);
sort(a+1,a+n+1);
FacInit();
f[0][0][0]=1;
for(int i=0;i<=n;i++){
for(int j=0;j<=i;j++){
for(int l=0;l<=m;l++){
if(!f[i][j][l]) continue;
if(l+1<=m) Add(f[i+1][j+1][l+1],f[i][j][l]*(j+1)%mod);
if(l+a[i+1]<=m) Add(f[i+1][j][l+a[i+1]],f[i][j][l]*2*j%mod);
if(j&&l+2*a[i+1]-1<=m) Add(f[i+1][j-1][l+2*a[i+1]-1],f[i][j][l]*(j-1)%mod);
}
}
}
ll ans=0;
for(int i=1;i<=m;i++) Add(ans,f[n][1][i]*C(m-i+n,n)%mod);
printf("%lld\n",ans);
return 0;
}

浙公网安备 33010602011771号