Solution

相当于要你计算这样一个式子:

\[\sum_{x = 0}^m \left( \begin{array}{} m \\ x \end{array} \right) \left( \begin{array}{} k \\ n - m + 2x \end{array}{} \right)
\]

考虑到\(m\)非常大, 而\(k\)却比较小, 我们尝试将\(x\)的\(m\)相关转化为\(k\)相关. 我们用如下现实意义来考虑: 令\(N = n - m\), 则我们相当于有两堆球, 第一堆球以单个球为单位, 总共\(N\)个, 我们要在其中取出\(i\)个; 第二堆球以一对球连在一起为单位, 总共有\(m\)对, 我们要在其中取出任意多对球, 拆开放入第一堆中, 然后问你在第一堆中取\(k\)个球总共有多少种的方案.

这个问题仍然不好解决, 我们继续考虑: 我们假设这\(k\)个球中, 总共用了第二堆球中的\(j\)对. 也就是说, 这\(k\)个球中\(i\)个是在第一堆中取来的, 剩下\(k - i\)个用到了第二堆中的\(j\)对球, 其中每一对既有可能被用了一个, 也有可能用了两个. 考虑方案数: 在第一堆中取\(i\)个显然就是\(\left( \begin{array}{} N \\ i \end{array}{} \right)\); 我们用f[i][j]来表示在第2堆中用到\(i\)对, 并且总共取出\(j\)个球的方案数, 考虑\(f[i][j]\)的递归式:

\[f[i][j] = f[i - 1][j - 1] \times 2 + f[i - 1][j - 2]
\]

这样以来, 总共的方案数就是

\[\sum_i \sum_j \left( \begin{array}{} N \\ i \end{array}{} \right) f[i][N - k]
\]

考虑到询问有\(500\)组, 我们要作一些预处理, 记忆化某些信息.


#include <cstdio>
#include <cctype> namespace Zeonfai
{
inline int getInt()
{
int a = 0, sgn = 1; char c;
while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
return a * sgn;
}
}
const int K = 300, MOD = (int)1e9 + 7;
int prod[K + 1], prodInv[K + 1], f[K + 1][K << 2], dwn[K + 1], _dwn[K + 1], pw[K + 1];
inline int power(int a, int x)
{
if(x < 0) return 0;
int res = 1;
for(; x; a = (long long)a * a % MOD, x >>= 1) if(x & 1) res = (long long)res * a % MOD;
return res;
}
inline int _C(int m)
{
if(m < 0) return 0;
return (long long)_dwn[m] * prodInv[m] % MOD;
}
inline int C(int m)
{
if(m < 0) return 0;
return (long long)dwn[m] * prodInv[m] % MOD;
}
inline void pretreat()
{
prod[0] = prodInv[0] = 1; for(int i = 1; i <= K; ++ i) prod[i] = (long long)prod[i - 1] * i % MOD, prodInv[i] = power(prod[i], MOD - 2);
f[0][0] = 1;
for(int i = 1; i <= K; ++ i) for(int j = 1; j <= i << 1; ++ j) f[i][j] = (f[i - 1][j - 1] * 2 % MOD + (j >= 2 ? f[i - 1][j - 2] : 0)) % MOD;
}
int main()
{ #ifndef ONLINE_JUDGE freopen("crash.in", "r", stdin);
freopen("crash.out", "w", stdout); #endif using namespace Zeonfai;
pretreat();
for(int T = getInt(); T --; )
{
int n = getInt(), m = getInt(), k = getInt(), ans = 0;
dwn[0] = 1; dwn[1] = m; for(int i = 2; i <= k; ++ i) dwn[i] = (long long)dwn[i - 1] * (m - i + 1) % MOD;
_dwn[0] = 1; _dwn[1] = n - m; for(int i = 2; i <= k; ++ i) _dwn[i] = (long long)_dwn[i - 1] * (n - m - i + 1) % MOD;
for(int i = 0; i <= k; ++ i) pw[i] = power(2, m - i);
for(int i = 0; i <= k; ++ i)
{
int cur = 0;
for(int j = (k - i + 1) / 2; j <= k - i; ++ j)
cur = (cur + (long long)C(j) % MOD * pw[j] % MOD * f[j][k - i] % MOD) % MOD;
ans = (ans + (long long)cur * _C(i) % MOD) % MOD;
}
printf("%d\n", ans);
}
}

2016北京集训测试赛(十七)Problem A: crash的游戏的更多相关文章

  1. 2016北京集训测试赛(十七)Problem C: 数组

    Solution 线段树好题. 我们考虑用last[i]表示\(i\)这个位置的颜色的上一个出现位置. 考虑以一个位置\(R\)为右端点的区间最远能向左延伸到什么位置: \(L = \max_{i \ ...

  2. 2016北京集训测试赛(十七)Problem B: 银河战舰

    Solution 好题, 又是长链剖分2333 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内 ...

  3. 2016北京集训测试赛(十六)Problem C: ball

    Solution 这是一道好题. 考虑球体的体积是怎么计算的: 我们令\(f_k(r)\)表示\(x\)维单位球的体积, 则 \[ f_k(1) = \int_{-1}^1 f_{k - 1}(\sq ...

  4. 2016北京集训测试赛(十六)Problem B: river

    Solution 这题实际上并不是构造题, 而是一道网络流. 我们考虑题目要求的一条路径应该是什么样子的: 它是一个环, 并且满足每个点有且仅有一条出边, 一条入边, 同时这两条边的权值还必须不一样. ...

  5. 2016北京集训测试赛(十六)Problem A: 任务安排

    Solution 这道题告诉我们, 不能看着数据范围来推测正解的时间复杂度. 事实证明, 只要常数足够小, \(5 \times 10^6\)也是可以跑\(O(n \log n)\)算法的!!! 这道 ...

  6. BZOJ 4543 2016北京集训测试赛(二)Problem B: thr 既 长链剖分学习笔记

    Solution 这题的解法很妙啊... 考虑这三个点可能的形态: 令它们的重心为距离到这三个点都相同的节点, 则其中两个点分别在重心的两棵子树中, 且到重心的距离相等; 第三个点可能在重心的一棵不同 ...

  7. 2016北京集训测试赛(十四)Problem B: 股神小D

    Solution 正解是一个\(\log\)的link-cut tree. 将一条边拆成两个事件, 按照事件排序, link-cut tree维护联通块大小即可. link-cut tree维护子树大 ...

  8. 2016北京集训测试赛(十四)Problem A: 股神小L

    Solution 考虑怎么卖最赚钱: 肯定是只卖不买啊(笑) 虽然说上面的想法很扯淡, 但它确实能给我们提供一种思路, 我们能不买就不买; 要买的时候就买最便宜的. 我们用一个优先队列来维护股票的价格 ...

  9. 2016北京集训测试赛(十三) Problem B: 网络战争

    Solution KD tree + 最小割树

随机推荐

  1. TortoiseSVN 同时检索多人的提交日志记录(如图操作)

  2. IOS开发学习笔记026-UITableView的使用

    UITableView的简单使用过程 简单介绍 两种样式 UITableViewStylePlain UITableViewStyleGrouped 数据显示需要设置数据源,数据源是符合遵守协议 &l ...

  3. MongoDB快速入门学习笔记6 MongoDB的文档删除操作

    db.集合名称.remove({query}, justOne)query:过滤条件,可选justOne:是否只删除查询到的第一条数据,值为true或者1时,只删除一条数据,默认为false,可选. ...

  4. 如何在win7下安装python包工具pip

    1. 在安装pip前,请确认你win系统中已经安装好了python,和easy_install工具,如果系统安装成功,easy_install在目录C:\Python27\Scripts 下面, 确认 ...

  5. 微信小程序-----校园头条详细开发之注册登录

    1.注册登录功能的实现 1.1结构 1.2 代码实现 1.2.1  为了通信的安全着想,在此我是通过小程序端获得code,然后传递给后端,在后端向微信后台发送api请求,解密,从而得到用户的唯一标示o ...

  6. Windows下Redis3.2.10及图像化工具redis-desktop-manager安装教程

    1.下载地址: GitHub地址:https://github-production-release-asset-2e65be.s3.amazonaws.com/3402186/bb1d10fc-3f ...

  7. 精通CSS高级Web标准解决方案(3-1 背景图像与图像替换)

    3.1背景图像基础 3.2图像替换 使用文本的图像并保留文本的方法.

  8. Visual C++ 连连看游戏源代码

    点击下载

  9. Leetcode 517.超级洗衣机

    超级洗衣机 假设有 n 台超级洗衣机放在同一排上.开始的时候,每台洗衣机内可能有一定量的衣服,也可能是空的. 在每一步操作中,你可以选择任意 m (1 ≤ m ≤ n) 台洗衣机,与此同时将每台洗衣机 ...

  10. xshell 连接redis

    当我们安装好redis 在本地测试启动,存,取都正常,但是无法远程连接redis. 在redis.conf的文件默认配置中有一配置是 bind 127.0.0.1,表示绑定访问该redis的地址只能是 ...