CF1764D Doremy‘s Pegging Game

题目描述

Doremy has n + 1 n+1 n+1 pegs. There are n n n red pegs arranged as vertices of a regular n n n -sided polygon, numbered from 1 1 1 to n n n in anti-clockwise order. There is also a blue peg of slightly smaller diameter in the middle of the polygon. A rubber band is stretched around the red pegs.

Doremy is very bored today and has decided to play a game. Initially, she has an empty array a a a . While the rubber band does not touch the blue peg, she will:

  1. choose i i i ( 1 ≤ i ≤ n 1\leq i \leq n 1in ) such that the red peg i i i has not been removed;
  2. remove the red peg i i i ;
  3. append i i i to the back of a a a .

Doremy wonders how many possible different arrays a a a can be produced by the following process. Since the answer can be big, you are only required to output it modulo p p p . p p p is guaranteed to be a prime number.
game with n = 9 n=9 n=9 and a = [ 7 , 5 , 2 , 8 , 3 , 9 , 4 ] a=[7,5,2,8,3,9,4] a=[7,5,2,8,3,9,4] and another game with n = 8 n=8 n=8 and a = [ 3 , 4 , 7 , 1 , 8 , 5 , 2 ] a=[3,4,7,1,8,5,2] a=[3,4,7,1,8,5,2]

题意简述

在墙上有 n n n 个红色的大钉子,编号为 1 … n 1\dots n 1n。有一根橡皮筋围在钉子上,形成了一个
n n n 边形。在正 n n n 边形的中心处有一个蓝色的小钉子,蓝色钉子的直径比红色钉子小。现
在你拔掉若干红色钉子,当橡皮筋最终碰到了蓝色钉子,游戏结束。问你有多少种有序的拔
掉红色钉子的方案。答案模一个质数 p p p.

题解

由于蓝色钉子的直径比红色钉子小,所以如果 n n n 为偶数,红钉子只剩一条直径的两个时,不会碰到蓝钉子。

所以若 n n n 为偶数,考虑最后剩下一条直径的钉子,其他 ( n − 2 ) (n-2) (n2) 个钉子随便拔,最后两个钉子二选一拔,有 n 2 \frac n2 2n 条直径,故方案数为 n ⋅ ( n − 2 ) ! n\cdot(n-2)! n(n2)!

现在考虑一般情况。设 t = ⌊ n 2 ⌋ t=\left\lfloor\frac n2\right\rfloor t=2n

观察最后结束钉子的位置,发现最少有长度为 t t t 的区间钉子被拔光,且这样的区间只有一个。

我们枚举被拔掉的区间长度 i i i t t t n − 2 n-2 n2
为什么枚举到 n − 2 n-2 n2 呢?因为区间外的两个钉子不能拔掉,否则长度会增加。
下面放个图方便理解
在这里插入图片描述上图为 n = 9 n=9 n=9 的情况。
如图,黑圈为被拔掉的区间,橙色三角形部分即为可能被拔的钉子的位置。在橙色三角形外的区间内的钉子,容易看到橡皮筋会碰到蓝钉子,是不合法的。

下图为 n = 10 n=10 n=10 的情况
在这里插入图片描述有三个钉子可作为最后一个被拔掉的钉子。

通过上两个图可发现,最后一个被拔掉的钉子的可能位置的数量为 2 t − i 2t-i 2ti

接下来枚举区间外的钉子中拔去 j j j 个钉子,从 0 0 0 n − i − 2 n-i-2 ni2。区间外两旁的钉子是不能拔的,上面已经说过了。

从可拔的 ( n − i − 2 ) (n-i-2) (ni2) 个钉子选 j j j 个钉子拔,然后区间内 i i i 个钉子全拔完,区间外要拔 j j j 个钉子,并且有一个钉子是要最后拔的,由于要考虑顺序,所以方案再乘上 ( i + j − 1 ) ! (i+j-1)! (i+j1)!

这样的长度为 i i i 的区间有 n n n 个。

所以对于长度为 i i i 的区间,方案即为 n ⋅ ( 2 t − 1 ) ∑ j = 0 n − i − 2 ( n − i − 2 j ) ( j + i − 1 ) ! n\cdot(2t-1)\sum\limits_{j=0}^{n-i-2}\dbinom{n-i-2}{j}\left(j+i-1\right)! n(2t1)j=0ni2(jni2)(j+i1)!

时间复杂度 O ( n 2 ) O(n^2) O(n2)

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod,f[5001],inv[5001],ans;
int n;
ll ksm(ll a,ll b)
{
    ll ans=1;
    while(b){
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
ll c(ll n,ll m)
{
    if(n<m) return 0;
    return f[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
    scanf("%d%lld",&n,&mod);
    f[0]=1;
    for(int i=1;i<=n;i++) f[i]=f[i-1]*i%mod;
    inv[n]=ksm(f[n],mod-2);
    for(int i=n-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
    int t=n/2;
    for(int i=t;i<n-1;i++){
        ll sum=0;
        for(int j=0;j<=n-i-2;j++) sum=(sum+c(n-i-2,j)*f[j+i-1])%mod;
        ans=(ans+sum*n%mod*(2*t-i))%mod;
    }
    if(n%2==0) ans=(ans+n*f[n-2])%mod;
    cout<<ans;
}
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值