首页 > 技术文章 > 蓝桥杯2019-省赛-C/C++-A组J题

memocean 2020-02-13 13:49 原文

用了组合数的性质和前缀和,但是只能过前面两个,后面再试试……

题目

组合数问题

时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分

【问题描述】

给 n, m, k,求有多少对 (i, j) 满足 1 ≤ i ≤ n, 0 ≤ j ≤ min(i, m) 且 C(i,j) ≡

0(mod k),k 是质数。其中 C(i,j)是组合数,表示从 i 个不同的数中选出 j 个组成

一个集合的方案数。

【输入格式】

第一行两个数 t, k,其中 t 代表该测试点包含 t 组询问,k 的意思与上文中 相同。

接下来 t 行每行两个整数 n, m,表示一组询问。

【输出格式】

输出 t 行,每行一个整数表示对应的答案。由于答案可能很大,请输出答 案除以 109 + 7 的余数。

【样例输入】

1 2

3 3

【样例输出】

1

【样例说明】

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

【样例输入】

2 5

4 5

6 7

【样例输出】

0

7

【样例输入】

3 23

23333333 23333333

233333333 233333333

2333333333 2333333333

【样例输出】

851883128

959557926

680723120

【数据规模和约定】

对于所有评测用例,1 ≤ k ≤ 10^8, 1 ≤ t ≤ 10^5, 1 ≤ n, m ≤ 10^18,且 k 是质数。 评测时将使用 10 个评测用例测试你的程序,每个评测用例的限制如下:

评测用例编号

t

n, m

k

1, 2

≤ 1

≤ 2000

≤ 100

3, 4

≤ 10^5

≤ 2000

≤ 100

5, 6, 7

≤ 100

≤ 10^18

≤ 100

8, 9, 10

≤ 10^5

≤ 10^18

≤ 10^8

代码

IMG_20200213_121924

 1 #include<iostream>
 2 #include<cmath> 
 3 #define ll long long 
 4 #define mod  (long long)(1e9+7) 
 5 using namespace std;
 6 ll c[2005][2005];
 7 ll s[2005][2005];
 8 void init(ll k){//依据组合数的性质产生杨辉三角图,并产生前缀和 
 9     c[0][0]=1;
10     for(int i=1;i<2001;i++){
11         c[i][0]=1;
12         c[i][i]=1;
13         for(int j=1;j<i;j++){
14             c[i][j]=(c[i-1][j-1]%k+c[i-1][j]%k)%k;//组合数的性质 
15             if(!c[i][j])  s[i][j]=1;
16             s[i][j]=(s[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1])%mod;
17         }
18         s[i][i]=s[i][i-1];
19     }
20 }
21 int main(){
22     ll t,k;
23     cin>>t>>k;
24     ll n,m;
25     init(k);
26     while(t--){
27         cin>>n>>m;
28         cout<<s[n][min(n,m)];
29     }
30     
31     
32 } 

推荐阅读