嘟嘟嘟




如果没有限制,而且必须选\(m\)件的话,就是隔板法\(C_{n + m - 1} ^ {m - 1}\)了。现在要选至多\(m\)件,那么就相当于新增一个板儿,分出的新的盒子表示“多出来的”,也就是说前\(m\)个盒子是选出来的宝具,这样就能满足至多\(m\)个的限制了,即\(C_{n + m} ^ {m}\)。

从公式这一角度来说,就是\(\sum _ {i = 0} ^ {n} C_ {i + m - 1} ^ {m - 1} = C_{n + m} ^ {m}\),至于证明,在我的另一篇博客上有,题解:bzoj4403 序列统计




现在我们加上了\(T\)这个限制。我一直在想,\(T\)这么小,显然可以\(2 ^ T\)暴力枚举,但那又有啥用咧?

后来某大佬的题解告诉我,你怎么就想不到容斥啊?

好像有道理,答案等于至少0个神器超过限制的方案数 - 至少1个神器超过限制方案数 + 至少3个超过限制 - ……而对于每一个方案数,我们先强制让这些神器选\(B_i + 1\)个,然后剩下的随便选,就是\(C_{n + m - \sum(B_i + 1)} ^ {m - \sum (B_i + 1)} = C_{n + m - \sum(B_i + 1)} ^ {n}\)。




最后因为模数小,上lucas。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
#include<assert.h>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e6 + 5;
In ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
In void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
In void MYFILE()
{
#ifndef mrclr
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
#endif
} int n, T, m, mod, b[20]; ll fac[maxn], inv[maxn];
In ll inc(ll a, ll b) {return a + b < mod ? a + b : a + b - mod;}
In ll C(int n, int m)
{
if(m > n) return 0;
return fac[n] * inv[n - m] % mod * inv[m] % mod;
}
In ll lucas(int n, int m)
{
ll ret = 1;
for(; m; n /= mod, m /= mod)
ret = ret * C(n % mod, m % mod) % mod;
return ret;
}
In ll quickpow(ll a, ll b)
{
ll ret = 1;
for(; b; b >>= 1, a = a * a % mod)
if(b & 1) ret = ret * a % mod;
return ret;
} In void init()
{
fac[0] = inv[0] = 1;
for(int i = 1; i < mod; ++i) fac[i] = fac[i - 1] * i % mod;
inv[mod - 1] = quickpow(fac[mod - 1], mod - 2);
for(int i = mod - 2; i; --i) inv[i] = inv[i + 1] * (i + 1) % mod;
} int main()
{
//MYFILE();
n = read(), T = read(), m = read(), mod = read();
for(int i = 1; i <= T; ++i) b[i] = read();
init();
ll ans = 0;
for(int i = 0; i < (1 << T); ++i)
{
int cnt = 0, tp = m;
for(int j = 1; j <= T; ++j)
if((i >> (j - 1)) & 1) ++cnt, tp -= b[j] + 1;
ans = inc(ans, (cnt & 1) ? mod - lucas(n + tp, n) : lucas(n + tp, n));
}
write(ans), enter;
return 0;
}

最新文章

  1. 查看openssl的版本
  2. linux 下进程通讯详解
  3. centos7 nginx配置httpsCenos(6.6/7.1)下从源码安装Python+Django+uwsgi+nginx环境部署(二)
  4. Android开发--环境的配置
  5. Android自定义进度条颜色
  6. C++模板详解
  7. Js自动截取字符串长度,添加省略号“……”
  8. Swiftly语言学习1
  9. 【翻译】编译Cordova项目
  10. Linux下使Shell 命令脱离终端在后台运行
  11. 从 Spring Cloud 看一个微服务框架的「五脏六腑」
  12. jupyter运行py文件(py文件和ipynb文件互转)
  13. VoiceXML简介
  14. 【微服务】.netCore eShopOnContainers 部署实践《一》
  15. change color3
  16. NUMA的取舍与优化设置
  17. 网络通信协议简介(TCP与UDP)
  18. C++中关键字explicit的作用
  19. C语言 &#183; 文本加密
  20. 【BZOJ4004】装备购买(线性基)

热门文章

  1. 『Python基础练习题』day02
  2. s5p6818 Overview
  3. AngularJS视图 ng-view
  4. Flutter 自定义绘制 View
  5. C# 应用程序文件夹结构
  6. Nginx中location模块的详细配置(含示例)
  7. KVM虚拟机高级设置——09 设置KVM虚拟机开机自动启动
  8. PAT Basic 1075 链表元素分类 (25 分)
  9. vs看源代码
  10. mysql 创建用户并授权数据库