【xsy2140】计数
Time Limit: 1000 ms Memory Limit: 256 MB
description

吐槽
所以说。。组合数的题是不是都是知道大致思路但是就是不会写qwq菜醒qwq
正题
这题其实感觉有点玄妙啊,自己想的话总是会想复杂。。但其实情况还是很好考虑的重点在于怎么枚举
首先讲一下大致思路
总共有4中不同的字符,相邻两个不能相同,那么我们可以考虑两种字符的排列(也就是先考虑\(A\)和\(B\)怎么放和\(C\)和\(D\)怎么放),然后再把\(AB\)的放法和\(CD\)的放法用插空的方式组合起来求得最后的答案
因为处理起来其实是一样的所以这里就只写\(AB\)的情况了
AB的情况
\(A\)和\(B\)有四种最基本的满足要求的摆放:
(1)\(A\) (2)\(B\) (3)\(AB\) (4)\(BA\)
我们枚举这些字符总共组成了多少个区间(这里的区间指的是在最后合并插空之后这段字符还是连在一起的,也就是说没有\(C\)和\(D\)插在中间),设总共有\(i\)个区间
我们再枚举一下(1)的个数,这时会发现每多一个(1)类区间,\(A\)的总数就会比\(B\)多一个,每多一个(2)类区间\(A\)就会比\(B\)少一个,而(3)和(4)的话不会对差有任何影响。
由于\(A\)的个数和\(B\)的个数是固定的,也就是说\(A\)和\(B\)的差是固定的,(1)的个数一旦确定,为了保证\(A\)和\(B\)的差满足条件,(2)的个数也就确定下来了。
我们记(1)类区间的个数为\(a\),那么(2)类区间的个数就是\(b = n1-n2+a\)
接着再看(3)和(4),会发现其实这两类本质上是一样的,我们只用枚举一类然后乘上组合数(其实就是\(2^i\),因为每一位可以是\(A\)或者\(B\)),这样我们就可以把这两类看做一类了,这剩下的一类的区间总数就是\(c=i - a -b\)
接下来看怎么算排列
首先对于(1)类和(2)类,我们用掉\(a\)个\(A\)和\(b\)个\(B\),排列的方案数显然是$C_{i}^{a} $ * \(C_{i-a}^{b}\)
对于剩下的(3)和(4),我们还有\(n1+n2-a-b\)个字符可以使用,也就是总共有\(d=\frac{n1+n2-a-b}{2}\)对\(AB\)
这\(d\)对字符首先要放进\(c\)个区间中(那么显然这里就要求\(d>=c\)了,在枚举的时候要注意范围),如果还有剩余,再将剩余的\(d-c\)对分配到\(i\)个区间中,那么方案就是\(C_{i+d-c+1}^{i-1}\)
为什么是这个东西嘞?
其实问题就相当于求\(i\)个非负数之和=\(d-c\)的方案数,我们先在等式两边都加上\(i\),然后变成\(i\)个正整数之和\(=i+d-c\),然后用隔板法就好了(枚举分割线在哪个空隙)。
这样操作是因为隔板法的使用前提是不能有空组(否则分割线的数量不一定是分成的份数-1),我们考虑将\(i+d-c\)分成i个数之后,每个数减去\(1\),得到i个非负整数(可以为0),此时这\(i\)个非负整数的和就是\(d-c\)了,也就是说这就是我们要求的其中一种方案,其他的情况同理,一一对应,所以这两个问题在组合数中是等价的
我们用\(f1\)来表示组成\(i\)个区间的方案数,那么就可以得到:
\(f1_i =\sum\limits_{a=0}^{n1+n2}C_{i}^{a}×C_{i-a}^{b}×2^c×C_{i+d-c+1}^{i-1}\)
用同样的方式来算\(C\)和\(D\)的方案,存到\(f2\)里面去
接下来看插空
插空有三种插法,下面用(AB)表示\(A\)和\(B\)组成的一个区间,(CD)表示\(C\)和\(D\)组成的一个区间,三种方法就可以这样表示:
1.(AB)(CD)(AB)(CD)(AB)
2.(CD)(AB)(CD)(AB)(CD)
3.(AB)(CD)(AB)(CD)(AB)(CD)(或者(AB)和(CD)的顺序反过来,所以算的时候要×2)
(其实会发现就是之前分别算\(AB\)区间和\(CD\)区间的三大类)
那么\(ans\)应该就是
\]
然后就十分愉快滴做完啦ovo
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define MOD 1000000007
using namespace std;
const int MAXN=4010;
ll f1[MAXN],f2[MAXN],two[MAXN],C[MAXN][MAXN];
ll ans;
int n1,n2,n3,n4;
int get_c(int n);
int get_f(int num1,int num2,ll *f);
ll calc(int c,int d);
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%d%d%d%d",&n1,&n2,&n3,&n4);
two[0]=1;
int sum=n1+n2+n3+n4;
for (int i=1;i<=sum;++i) two[i]=(two[i-1]<<1)%MOD;
get_c(sum);
get_f(n1,n2,f1);
get_f(n3,n4,f2);
for (int i=1;i<=n1+n2;++i)
ans=(ans+f1[i]*f2[i-1]%MOD+f1[i]*f2[i+1]%MOD+2LL*f1[i]*f2[i]%MOD)%MOD;
printf("%lld\n",ans);
}
int get_c(int n){
for (int i=0;i<=n;++i){
C[i][0]=1; C[i][i]=1;
for (int j=1;j<i;++j)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
}
}
int get_f(int num1,int num2,ll *f){
int a,b,c,d,sum=num1+num2;
for (int i=0;i<=num1+num2;++i){
for (a=0;a<=i;++a){//枚举(1)
b=num1-num2+a;//(2)
c=i-a-b;//(3)+(4)要填区间
d=(sum-a-b)/2;//(3)+(4)可用对
if (b<0||c<0||d<0||d<c) continue;
f[i]=(f[i]+C[i][a]*C[i-a][b]%MOD*two[c]%MOD*calc(i,d-c)%MOD)%MOD;
}
}
}
ll calc(int c,int d){//c个非负整数之和=d,枚举所有区间填了一个之后剩下的放哪里
if (!c) return d==0;
return C[c+d-1][c-1];
}
【xsy2140】计数的更多相关文章
- 计数排序(counting-sort)——算法导论(9)
1. 比较排序算法的下界 (1) 比较排序 到目前为止,我们已经介绍了几种能在O(nlgn)时间内排序n个数的算法:归并排序和堆排序达到了最坏情况下的上界:快速排序在平均情况下达到该上界. ...
- Objective-C内存管理之引用计数
初学者在学习Objective-c的时候,很容易在内存管理这一部分陷入混乱状态,很大一部分原因是没有弄清楚引用计数的原理,搞不明白对象的引用数量,这样就当然无法彻底释放对象的内存了,苹果官方文档在内存 ...
- 最小生成树计数 bzoj 1016
最小生成树计数 (1s 128M) award [问题描述] 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一 ...
- swift学习笔记5——其它部分(自动引用计数、错误处理、泛型...)
之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...
- [LeetCode] Count and Say 计数和读法
The count-and-say sequence is the sequence of integers beginning as follows:1, 11, 21, 1211, 111221, ...
- C++ 引用计数技术及智能指针的简单实现
一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...
- css-列表或标题的多级计数
利用css实现多级计数,比如1/1.1/1.1.1这种层层嵌套的计数,主要利用到counter-reset/counter-increment/counter/content/:before. 一.标 ...
- csv 中 数值被自动转换成科学计数法 的问题 excel打开后数字用科学计数法显示且低位变0的解决方法
保存在csv中的 013812345678,前面的0会被去掉,后面是科学计数法显示.保存成 col1,="013812345678" 即可. 注意,分隔符逗号后面直接接“=”等号. ...
- 用uniq来处理文件重复数据--交集,差集,计数等(转)
经常有这样的需求:两个文本文件要求取重复的行或只取不重复的,简单的情况下用sort和uniq来处理是非常方便的: 利用现存两个文件,生成一个新的文件 取出两个文件的并集(重复的行只保留一份) 取出两个 ...
随机推荐
- mybatis like条件添加%的方法
使用 MySQL可以使用CONCAT函数.例: <if test="userName != null and userName != ''"> and user_nam ...
- 一起学微软Power BI系列-使用技巧(6) 连接Sqlite数据库
好久没有研究Power BI了,看到高飞大神弄的东西,太惭愧了.今天有个小东西,数据在Sqlite里面,想倒腾到Power BI Desktop里面折腾一下,结果发现还不直接支持.所以只好硬着头皮上去 ...
- linux磁盘及分区详解
1.Linux 分区简介 1.1 主分区 vs 扩展分区 硬盘分区表中最多能存储四个分区,但我们实际使用时一般只分为两个分区,一个是主分区(Primary Partion)一个是扩展分区(extend ...
- jquery validate 动态增加删除验证规则(转载)
页面加载完成初始化form validate $("#user_regForm").validate({ errorPlacement: function(error, eleme ...
- 枚举enum学习小记
参考文献: [1]C++程序设计语言(特别版), 裘宗燕译, 机械工业出版社 [2]C++ Primer (3rd Ed.), S.B. Lippman and J. Lajoie, 人民邮电出版社 ...
- InputStream中通过mark和reset方法重复利用缓存
通过缓存InputStream可重复利用一个InputStream,但是要缓存一整个InputStream内存压力可能是比较大的.如果第一次读取InputStream是用来判断文件流类型,文件编码等用 ...
- JPA数据懒加载LAZY配合事务@Transactional使用(三)
上篇博文<JPA数据懒加载LAZY和实时加载EAGER(二)>讲到,如果使用懒加载来调用关联数据,必须要保证主查询session(数据库连接会话)的生命周期没有结束,否则,你是无法抽取到数 ...
- 在web工程中设置首页的页面
有些时候删除了系统自带的index.jsp删除后会出现如下图错误 解决办法,新创建一个以你自己命名的jsp文件,然后在对该web工程的WEB-INF 目录下的web.xml进行添加加上下面的注释所带的 ...
- Windows系统上Redis的安装
Redis 安装 Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你系统 ...
- 使用phpstorm提交svn代码版本管理系统遇到的问题解决办法
1.当自己提交代码的时候显示out of date的时候,表示我们本地的代码过时啦,需要更新一下再提交. 即:更新一下再提交即可. 2.当自己的代码和服务器上的冲突的时候,我们右键点击冲突的文件,选择 ...