NOIP2016Day2T1-组合数问题

本文介绍了一种解决组合数问题的方法,即计算给定n、m和k的情况下,有多少对(i,j)使得C(i,j)是k的倍数。通过构建杨辉三角,并使用动态规划方法来快速求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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,mn,m的意义见【问题描述

输出

t行,每行一个整数代表所有的0in,0jmin(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.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JackflyDC

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

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

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

打赏作者

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

抵扣说明:

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

余额充值