NOIP2016Day2T1-组合数问题

A: 组合数问题

时间限制: 1 Sec   内存限制: 512 MB

题目描述

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

其中 n ! =  1 × 2 ×···× n

小葱想知道如果给定 n , mk ,对于所有的 0 ≤ in , 0 ≤ jmin (i , m ) 有多少对


(i , j ) 满足C(i,j)是 k 的倍数。

输入

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

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

输出

t 行,每行一个整数代表所有的 0 i n , 0 j min (i , m ) 中有多少对 (i , j ) 满足C(i,j) k 的倍数。

样例输入

1 2
3 3

2 5
4 5
6 7

样例输出

1

0
7

提示

【样例 1 说明】

在所有可能的情况中,只有C(2,1)=2 2的倍数

【子任务】

测试点

n

m

k

t

1

3

3

= 2

= 1

2

= 3

104

3

7

7

= 4

= 1

4

= 5

104

5

10

10

= 6

= 1

6

= 7

104

7

20

100

= 8

= 1

8

= 9

104

9

25

2000

= 10

= 1

10

= 11

104

11

60

20

= 12

= 1

12

= 13

104

13

 

100

25

= 14

= 1

14

= 15

104

15

60

= 16

= 1

16

= 17

104

17

 

2000

100

= 18

= 1

18

= 19

104

19

2000

= 20

= 1

20

= 21

104

我们可以先求出C(i,j)的值。通过找规律可以发现这是一个杨辉三角。可以求出记为f[i,j]并 mod k。然后记dp[i,j]为C(i,j)的个数。当f[i,j]=0时,dp[i,j]=dp[i,j-1]+1,否则dp[i,j]=dp[i,j-1]。最后每组从1到m循环一遍求解即可。

Code:
var
  t,k,i,j,ans,n,m:longint;
  dp,f:array[0..2000,0..2000] of longint;
begin
  readln(t,k);
  for i:=0 to 2000 do f[i,0]:=1;
  for i:=1 to 2000 do
    for j:=1 to i do
      f[i,j]:=(f[i-1,j]+f[i-1,j-1]) mod k;
  for i:=1 to 2000 do
    for j:=1 to i do
      if f[i,j]=0 then
        dp[i,j]:=dp[i,j-1]+1 else
          dp[i,j]:=dp[i,j-1];
  for i:=1 to t do
  begin
    ans:=0;
    readln(n,m);
    for j:=1 to n do
      if j>m then ans:=ans+dp[j,m]
        else ans:=ans+dp[j,j];
    writeln(ans);
  end;
end.
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JackflyDC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值