【NOIP2016提高组复赛官方数据】组合数问题

题面

Description

在这里插入图片描述

Input

在这里插入图片描述

Output

在这里插入图片描述

Sample Input

Sample Input1:

1 2
3 3

Sample Input2:

2 5
4 5
6 7

Sample Output

Sample Output1:

1

Sample Output2:

0
7

Data Constraint

在这里插入图片描述

思路

这题找一下规律可以很容易发现,它是杨辉三角形。所以我们只需要在 O ( n m ) O(nm) O(nm)的复杂度内预处理出一个杨辉三角,将每个数 ( m o d k ) \pmod k (modk),如果它为0,表示它是k的倍数,用二维前缀和处理一下即可。
查询时间复杂度为 O ( 1 ) O(1) O(1),所以时间复杂度为 O ( t + n m ) O(t+nm) O(t+nm)

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
int t,k,n,m,f[2005][2005],a[2005][2005];
int main()
{
    
    
	freopen("problem.in","r",stdin);
	freopen("problem.out","w",stdout);
	scanf("%d%d",&t,&k);
	a[0][0]=1%k;
	if(!a[0][0]) f[0][0]=1;
	for(int i=1;i<=2000;i++)
		for(int j=0;j<=2000;j++)
		{
    
    
			if(j<=i)
			{
    
    
				if(j==0||j==i) a[i][j]=1%k;
				else a[i][j]=(a[i-1][j-1]+a[i-1][j])%k;
			}
			int bz=0;
			if(!a[i][j]&&j<=i) bz=1;
			f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+bz;
		}
	for(int i=1;i<=t;i++)
	{
    
    
		scanf("%d%d",&n,&m);
		printf("%d\n",f[n][m]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46830417/article/details/113137827