[SDOI 2011]黑白棋

Description

题库链接

给出一个 \(1\times n\) 的棋盘,棋盘上有 \(k\) 个棋子,一半是黑色,一半是白色。最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同。
\(A\) 可以移动白色棋子,小 \(B\) 可以移动黑色的棋子,他们每次操作可以移动 \(1\sim d\) 个棋子。
每当移动某一个棋子时,这个棋子不能跨越两边的棋子,当然也不可以出界。当谁不可以操作时,谁就失败了。
\(A\) 和小 \(B\) 轮流操作,现在小 \(A\) 先移动,问有多少种初始棋子的布局使他胜利。

\(1\leq n\leq 10000,1\leq k\leq 100\)

Solution

是一道假题...参考了 黄学长的做法 ... 具体可以参见他的博客。

Code

#include <bits/stdc++.h>
using namespace std;
const int yzh = 1000000007, N = 10000;

int n, k, d, a[N+5], b[N+5], bin[20], f[16][N+5];

int C(int n, int m) {return 1ll*a[n]*b[m]%yzh*b[n-m]%yzh; }
void work() {
    scanf("%d%d%d", &n, &k, &d);
    a[0] = b[0] = a[1] = b[1] = bin[0] = 1;
    for (int i = 2; i <= n; i++) b[i] = -1ll*yzh/i*b[yzh%i]%yzh;
    for (int i = 2; i <= n; i++) a[i] = 1ll*i*a[i-1]%yzh, b[i] = 1ll*b[i]*b[i-1]%yzh;
    for (int i = 1; i < 20; i++) bin[i] = (bin[i-1]<<1);
    f[0][0] = 1;
    for (int i = 0; i < 15; i++)
        for (int j = 0; j <= n-k; j++)
            for (int p = 0; p*(d+1) <= k/2 && p*(d+1)*bin[i]+j <= n-k; p++)
                (f[i+1][p*(d+1)*bin[i]+j] += 1ll*f[i][j]*C(k/2, p*(d+1))%yzh) %= yzh;
    int ans = C(n, k);
    for (int i = 0; i <= n-k; i++)
        (ans -= 1ll*f[15][i]*C(n-k/2-i, k/2)%yzh) %= yzh;
    printf("%d\n", (ans+yzh)%yzh);
}
int main() {work(); return 0; }

转载于:https://www.cnblogs.com/NaVi-Awson/p/8641502.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值