码迷,mamicode.com
首页 > 其他好文 > 详细

noip2016组合数问题

时间:2018-11-01 13:38:58      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:reg   i++   oid   数据   mat   分享   输入   line   情况下   

题目描述

组合数 Cnm? 表示的是从 n 个物品中选出 m 个物品的方案数。举个例子,从 (1,2,3) 三个物品中选择两个物品可以有(1,2),(1,3),(2,3) 这三种选择方法。根据组合数的定义,我们可以给出计算组合数 Cnm? 的一般公式:

Cnm?=m!/(n?m)!n!?

其中n!=1×2×?×n;特别地,定义 0!=1。

小葱想知道如果给定 n,m 和 k,对于所有的 0in,0jmin(i,m) 有多少对 (i,j) 满足 Cij? 是 k 的倍数。

输入输出格式

输入格式:

 

第一行有两个整数 t,k,其中 t代表该测试点总共有多少组测试数据,k 的意义见问题描述。

接下来 t行每行两个整数 n,m,其中 n,m 的意义见问题描述。

 

输出格式:

 

共 t 行,每行一个整数代表所有的0in,0jmin(i,m) 中有多少对 (i,j) 满足 Cij? 是 k 的倍数。

 

输入输出样例

输入样例#1: 复制
1 2
3 3
输出样例#1: 复制
1
输入样例#2: 复制
2 5
4 5
6 7
输出样例#2: 复制
0
7

说明

【样例1说明】

在所有可能的情况中,只有C_2^1 = 2C21?=2是2的倍数。

【子任务】

技术分享图片

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 int i,j,n,m,t,k,ans[2005][2005],c[2005][2005];
 7 void build()
 8 {
 9     c[0][0] = 1;
10     c[1][0] = 1;
11     c[1][1] = 1;
12     for(i = 2;i <= 2000;i++)
13     {
14         c[i][0] = 1;
15         for(j = 1;j <= i;j++)
16         {
17             c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % k; //第j个选他的可能性和不选他的可能性加在一起 
18             ans[i][j] = ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1];//求前缀和 
19             if(c[i][j] == 0) //代表是k的倍数 
20             ans[i][j]++;
21             ans[i][i + 1] = ans[i][i]; //继承 
22         }
23     }
24 }
25 int main()
26 {
27     scanf("%d %d",&t,&k);
28     build();
29     for(i = 1;i <= t;i++)
30     {
31         scanf("%d %d",&n,&m);
32         if(n < m)
33         printf("%d",ans[n][n]);//在这种情况下最多也只能取到n 
34         else
35         printf("%d",ans[n][m]);
36         if(i != t)
37         printf("\n");
38     }
39     return 0;
40 }

*******万恶的组合数,竟然还有前缀和这个操作。

noip2016组合数问题

标签:reg   i++   oid   数据   mat   分享   输入   line   情况下   

原文地址:https://www.cnblogs.com/rax-/p/9888572.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!