NOIP2016 D2T1 组合数问题
数学真重要啊……
其实解这一题的关键就是组合恒等式:C(n,m)=C(n-1,m)+C(n-1,m-1),然后再知道组合数的矩阵(杨辉三角)和题中n,m的关系就很容易解决了(然而做这题之前我并不知道组合恒等式于是杯具了)
由上文提到的几何恒等式,我们可以将组合数打成如下矩阵(C(i,j)行数代表i,列数代表j(均从0开始))
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
………………
接下来我们来看要求的结论:求所有的0≤i≤n,0≤j≤min(i,m)中有多少对(i,j)使C(i,j)是k的倍数。
我乍一看到min(i,m)以为这题很复杂。但放到图中一看,想到i≥j,我们惊奇地发现,我们要求的结论就是图中共n+1行,m+1列(包括i=0,j=0)中有多少组合数是k的倍数。
画个图给大家感受一下(灵魂画手)
比如n=3,m=2,那我们就是要求图中这个部分组合数是k的倍数的数量
但询问量特别大,所以我们可以预处理一下
每访问到一个元素都枚举一个矩形很慢,但我们有递推式:d[i][j]=d[i-1][j]+d[i][j-1]-d[i-1][j-1]+!(zuhe[i][j]%k)
拿上面那个矩阵举例子
黑色部分的信息(被k整除的组合数个数)d[3][2]可以表示为红色部分的信息d[2][2]加上绿色部分的信息d[3][1]减去蓝色部分的信息d[2][1](此信息满足区间加法和减法性质)
事实上因为c++数组自动初始化为0的问题,所以我们只会初始化有组合数部分的d值(即i≥j),那么m<n的时候怎么办呢?
很显然图中黑色部分的信息等于红色部分的信息(因为组合数数量相等)
所以当m<n时d[m][n]=d[m][m](在递推的时候处理或是在输出的时候处理均可,我是在输出的时候处理的)
另外此处递推的时候注意一下边界问题(i=j时),此时d[i-1][j]我们没有更新(因为i-1<j),所以此时的d[i][j]=d[i][j-1]+!(zuhe[i][j]%k)
即黑色部分的信息等于红色部分的信息加上当前点的信息
还有一点小tip就是2000个组合数会很大,所以我们递推组合数的时候就将它模k,这样模k=0的组合数在表中的值就是0,上面的递推公式就改为:d[i][j]=d[i-1][j]+d[i][j-1]-d[i-1][j-1]+!zuhe[i][j](i>j),d[i][i]=d[i][i-1]+!zuhe[i][i]
剩下的就很简单了,记得初始化zuhe[1][0]=zuhe[1][1]=1即可
代码如下:
#include<cstdio>
using namespace std;
int t,k,n,m;
int zuhe[][];//存储组合数(%k意义下)
int d[][];//存储方案个数
int main()
{
scanf("%d%d",&t,&k);
zuhe[][]=zuhe[][]=;//初始化C(1,0)=C(1,1)=1
for(int i=;i<=;i++)
for(int j=;j<=i;j++)
zuhe[i][j]=(zuhe[i-][j]+zuhe[i-][j-])%k;
for(int i=;i<=;i++)
{
for(int j=;j<i;j++)
d[i][j]=d[i-][j]+d[i][j-]-d[i-][j-]+!zuhe[i][j];
d[i][i]=d[i][i-]+!zuhe[i][i];
}
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
if(n<m)
m=n;
printf("%d\n",d[n][m]);
}
return ;
}
NOIP2016 D2T1 组合数问题的更多相关文章
- CJOJ 2255 【NOIP2016】组合数问题 / Luogu 2822 组合数问题 (递推)
CJOJ 2255 [NOIP2016]组合数问题 / Luogu 2822 组合数问题 (递推) Description 组合数\[C^m_n\]表示的是从n个物品中选出m个物品的方案数.举个例子, ...
- 题解 【NOIP2016】组合数问题
[NOIP2016]组合数问题 Description Input 第一行有两个整数t, k,其中t代表该测试点总共有多少组测试数据,k的意义见[问题描述]. 接下来t行每行两个整数n, m,其中n, ...
- UOJ263 【NOIP2016】组合数问题
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- NOIP2016 D2T1 組合數問題(problem)
题目描述 组合数C(n,m)表示的是从n个物品中选出m个物品的方案数.举个例子,从(1,2,3) 三个物品中选择两个物品可以有(1,2),(1,3),(2,3)这三种选择方法.根据组合数的定 义,我们 ...
- 【NOIP2016】组合数问题 题解(组合数学+递推)
题目链接 题目大意:给定$n,m,k$,求满足$k|C_i^j$的$C_i^j$的个数.$(0\leq i\leq n,1\leq j\leq \min(i,m))$. --------------- ...
- 【NOIP2016】组合数问题
写着玩玩…… 反正超级sb题. #include<bits/stdc++.h> typedef long long ll; using namespace std; ll c[][],h[ ...
- 【NOIP2016】 组合数问题
[题目链接] 点击打开链接 [算法] 杨辉三角 + 二维前缀和 O(1)计算答案 [代码] #include<bits/stdc++.h> using namespace std; #de ...
- $Noip2016/Luogu2822$ 组合数问题
$Luogu$ 看这题题解的时候看到一个好可爱的表情(●'◡'●)ノ♥ $Sol$ 首先注意到这题的模数是$k$.然而$k$并不一定是质数,所以不能用$C_n^m=\frac{n!}{m!(n-m)! ...
- 组合数取模及Lucas定理
引入: 组合数C(m,n)表示在m个不同的元素中取出n个元素(不要求有序),产生的方案数.定义式:C(m,n)=m!/(n!*(m-n)!)(并不会使用LaTex QAQ). 根据题目中对组合数的需要 ...
随机推荐
- 【1】mongoDB 的安装及启动
MongoDB是一个面向文档(document-oriented)的数据库,不是关系型数据库.与关系型数据库相比,面向文档的数据库没有"行"的概念,取而代之的是"文档&q ...
- pgAdmin III 使用图解
pgAdmin III简介 要打开一个到服务的连接,在树中选择所需的服务,并双击它,或使用“工具”菜单上的连接即可. 一.主窗体 在主窗口中,显示数据库的结构.您可以创建新的对象,删除和编辑现有的对象 ...
- CSS3—— 多列 用户界面 图片 按钮
多列 将文本内容设计成像报纸一样的多列布局 多列创建 间隙 列边框 边框颜色+宽度 指定列的宽度 指定元素跨越多少列 用户界面 由用户调整元素大小[谷歌浏览器等] 以确切的方式定义适应某个区域的具体内 ...
- 【MM系列】SAP PO增强BADI
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP PO增强BADI 前言部 ...
- 浅谈vue学习之组件通信
vue用组件化简化了我们编写代码的复杂度,组件之间经常会出现数据传递的情况,那么组件之间是怎样通信的呢? 使用props传递数据 组件实例的作用域是孤立的.这意味着不能 (也不应该) 在子组件的模板内 ...
- ---Mock---基本使用
一.mock解决的问题 开发时,后端还没完成数据输出,前端只好写静态模拟数据.数据太长了,将数据写在js文件里,完成后挨个改url.某些逻辑复杂的代码,加入或去除模拟数据时得小心翼翼.想要尽可能还原真 ...
- 20191127 Spring Boot官方文档学习(4.25)
4.25. Testing Spring Boot提供了许多实用程序和注解,可以在测试应用程序时提供帮助.测试支持由两个模块提供:spring-boot-test包含核心项,spring-boot-t ...
- Spark集成的包与引入包冲突
今天在编写Spark应用的时候,想把处理结果输出为JSON字符串,查到Java比较常用的JSON处理包gson,按照其API编写代码后运行程序,总是出现"NoSuchMethodExcept ...
- 【C语言--数据结构】线性顺序表
线性表的本质: 1.线性表(List)是零个或者多个数据元素的集合: 2.线性表中的数据元素之间是有顺序的: 3.线性表中的数据元素个数是有限的: 4.线性表中的数据元素的类型必须相同: 定义: 线性 ...
- CentOS7创建本地源过程
1)使用yum安装http服务(主节点) yum -y install httpd 2)将httpd服务加入系统自启动服务并设置开机启动 systemctl start httpd #启动apache ...