这是一道很好的组合数学题。

对于和我一样五音里面有六音不全的人来说,我们就应该转换一下题目的意思:

一句话题意:

题目的意思就是说要从一个有 n 个元素的集合当中选出一个长度为m的集合,然后满足:

1.无序性

2.这每个音阶出现的次数为偶数

3.这些元素满足单一性

4.不为空集

所以考虑组合:::

上过高中的应该都知道,一个拥有 n 个元素的集合,那么它的子集的数量就是 \(2^n\) - 1,那么对于每一个 \(i\),组合的数量就是 \(A_{2^n-1}^{i-1}\) ,之后我们可以发现:

\(2^n\) - 1 的数值大小是固定的,所以我们可以先计算所有的变量之后在最后再去对 \(m!\)进行操作,故可以预处理:

a[0] = 1;//边界
for(register int i=1;i<=m;++i)
a[i] = a[i-1] * (sum - i + 1) % mod;

说实话,还有一种预处理方式,但我导完式子之后就不想打了,在这里还是推导一遍吧。。。

\[A_{2^n-1}^{i-1} = \frac{(2^n - 1)!}{(2^n -1-i+1)!} = \frac{\prod_{j=1}^{2^n-1}j}{\prod_{j=1}^{2^n-i}j} =
\]
\[\frac{\prod_{j={2^n-i+1}}^{2^n-1}j * \prod_{j=1}^{2^n-i}j}{\prod_{j=1}^{2^n-i}j}
= {\prod_{j={2^n-i+1}}^{2^n-1}j}
\]

这个式子的代码自己敲吧,反正我是不想敲

然后就可以开始dp了:

三种转移:

1.\(f_i = a_i\)

2.\(f_i = f_i - f_{i-1}\)

3.\(f_i = (f_i - f_{i-2} * (i-1) * (2^n - i)\)

相信前面的两个式子大家应该都可以看的懂,那就来解释一下第三个吧:

在选到第\(i\)个数的时候,那么就只剩下\(i-1\)个数来备选,并且我们在实现\(2^n-1\)的时候,我们可以用\(sum - i + 2\)来实现\(sum = 2^n -1\)

所以code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline void f()
{cout<<"fuck"<<endl;}
inline void openfile()
{freopen("t.txt","r",stdin);}
namespace xin
{
#define m(c,num) memset(c,num,sizeof(c))
int n,m;
const int maxn = 1e6+10;
inline int ksm(int x,int y,int mod)
{
int ans = 1;
while(y)
{
if(y & 1) ans = ans * x % mod,ans %= mod;
x = x * x % mod,x %= mod;
y >>= 1;
}
return ans;
}
inline void qmod(int &x,int mod)
{x %= mod;}
int a[maxn],f[maxn];
const int mod = 1e8+7;
inline short main()
{
// openfile();
scanf("%lld%lld",&n,&m);
int sum = ksm(2,n,mod) - 1;
a[0] = f[0] = 1;
for(register int i=1;i<=m;++i)
a[i] = a[i-1] * (sum - i + 1) % mod,qmod(a[i],mod);
for(register int i=2;i<=m;++i)
{
f[i] = a[i-1];
f[i] = f[i] - f[i-1];
f[i] = (f[i] - f[i-2] % mod * (i - 1)% mod * (sum - i + 2) % mod + mod) % mod;
}
int jie = 1;
for(register int i=1;i<=m;++i) jie = jie * i % mod,qmod(jie,mod);
int inv = ksm(jie,mod-2,mod);
cout<<f[m] * inv % mod<<endl;
return 0;
}
}
signed main() {return xin::main();}

忽略神仙码风。。。

[HNOI]2011卡农的更多相关文章

  1. [HNOI 2011]卡农

    Description 题库链接 在集合 \(S=\{1,2,...,n\}\) 中选出 \(m\) 个子集,满足三点性质: 所有选出的 \(m\) 个子集都不能为空. 所有选出的 \(m\) 个子集 ...

  2. P3214 [HNOI2011]卡农

    题目 P3214 [HNOI2011]卡农 在被一题容斥\(dp\)完虐之后,打算做一做集合容斥这类的题了 第一次深感HNOI的毒瘤(题做得太少了!!) 做法 求\([1,n]\)组成的集合中选\(m ...

  3. [BZOJ2339][HNOI2011]卡农

    [BZOJ2339][HNOI2011]卡农 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见"试题描述" 输出示例 见& ...

  4. [HNOI2011]卡农

    题目描述 众所周知卡农是一种复调音乐的写作技法,小余在听卡农音乐时灵感大发,发明了一种新的音乐谱写规则.他将声音分成 n 个音阶,并将音乐分成若干个片段.音乐的每个片段都是由 1 到 n 个音阶构成的 ...

  5. bzoj2339[HNOI2011]卡农 dp+容斥

    2339: [HNOI2011]卡农 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 842  Solved: 510[Submit][Status][ ...

  6. BZOJ2339[HNOI2011]卡农——递推+组合数

    题目链接: [HNOI2011]卡农 题目要求从$S=\{1,2,3……n\}$中选出$m$个子集满足以下三个条件: 1.不能选空集 2.不能选相同的两个子集 3.每种元素出现次数必须为偶数次 我们考 ...

  7. BZOJ 2339 【HNOI2011】 卡农

    题目链接:卡农 听说这道题是经典题? 首先明确一下题意(我在这里纠结了好久):有\(n\)个数,要求你选出\(m\)个不同的子集,使得每个数都出现了偶数次.无先后顺序. 这道题就是一道数学题.显然我们 ...

  8. 【BZOJ2339】卡农(递推,容斥)

    [BZOJ2339]卡农(递推,容斥) 题面 BZOJ 题解 先简化一下题意: 在\([1,2^n-1]\)中选择不重复的\(m\)个数,使得他们异或和为\(0\)的方案数. 我们设\(f[i]\)表 ...

  9. 【BZOJ2339】[HNOI2011]卡农 组合数+容斥

    [BZOJ2339][HNOI2011]卡农 题解:虽然集合具有无序性,但是为了方便,我们先考虑有序的情况,最后将答案除以m!即可. 考虑DP.如果我们已经知道了前m-1个集合,那么第m个集合已经是确 ...

随机推荐

  1. 从一道高大上的面试题来学习位图算法BitMap

    今天我偶然刷到了一篇文章,"华为二面:一个文件里面有5亿个数据,一行一个,没有重复的,进行排序".不知道又是哪个无良媒体瞎起的标题,夺人眼球. 不过说归说,这题听着就很高大上,5亿 ...

  2. 密码学系列之:feistel cipher

    密码学系列之:feistel cipher 简介 feistel cipher也叫做Luby–Rackoff分组密码,是用来构建分组加密算法的对称结构.它是由德籍密码学家Horst Feistel在I ...

  3. 一、安装Tomcat服务器

    [root@ web1 ~]# yum -y install java-1.8.0-openjdk   #安装jdk [root@web1 ~]# yum -y install java-1.8.0- ...

  4. 四、缓存DNS

    作用:缓存解析结果,提高解析速度 搭建方式: 1.全局转发,所有的DNS解析请求全部转发给公网DNS 2.根域迭代,所有的DNS解析请求全部发给根域DNS服务器 真机上实现缓存DNS服务器 1.搭建Y ...

  5. 【NX二次开发】Block UI 字符串

    属性说明:     BlockID     String 控件ID     Enable     Logical 是否可操作     Group     Logical 是否分组     Label  ...

  6. 【NX二次开发】镜像对象

    使用uf5946获取镜像矩阵注意:uf5946镜像这个函数,只能用#define UF_plane_type=46这种类型的数据作为镜像面,不能用#define UF_datum_plane_type ...

  7. 卢卡斯定理&&中国剩余定理

    卢卡斯定理(模数较小,且是质数) 式子C(m,n)=C(m/p,n/p)*C(m%p,n%p)%p 至于证明(我也不会QAQ,只要记住公式也该就好了). 同时卢卡斯定理一般用于组合数取模上 1.首先当 ...

  8. StringUtils中的常量

    //空格字符串 public static final String SPACE = " "; //空字符串 public static final String EMPTY = ...

  9. Go语言Slice作为函数参数详解

    Go语言Slice作为函数参数详解 前言 首先要明确Go语言中实质只有值传递,引用传递和指针传递是相对于参数类型来说. 个人认为上诉的结论不对,把引用类型看做对指针的封装,一般封装为结构体,结构体是值 ...

  10. Zabbix5.0Yum安装

    1.1.操作系统配置: 1.操作系统属性(虚拟机下环境): (1)操作系统版本: [root@localhost ~]# cat /etc/redhat-release CentOS Linux re ...