P2822 组合数问题

本文介绍了一种利用组合数公式预处理模k的结果,并通过二维前缀和求解特定条件下的组合数求和问题。该方法适用于解决给定n, m和k值,计算Cij mod k等于0的组合数之和的问题,时间复杂度为O(n^2+T),适用于数据范围不超过3000的题目。
摘要由CSDN通过智能技术生成
H y p e r l i n k Hyperlink Hyperlink

https://www.luogu.com.cn/problem/P2822


D e s c r i p t i o n Description Description

给定 T T T组数据和一个数 k k k,每组数据给定一个 n , m n,m n,m,要求回答
∑ i = 1 n ∑ j = 1 m i n ( n , m ) [ C i j m o d    k = = 0 ] \sum _{i=1}^n \sum_{j=1}^{min(n,m)} [C_i^j\mod k==0] i=1nj=1min(n,m)[Cijmodk==0]

数据范围: n , m ≤ 3 × 1 0 3 , T ≤ 1 0 4 , k ≤ 21 n,m\leq 3\times 10^3,T\leq 10^4,k\leq 21 n,m3×103,T104,k21


S o l u t i o n Solution Solution

利用组合数公式 C i j = C i − 1 j − 1 + C i − 1 j C_i^j=C_{i-1}^{j-1}+C_{i-1}^j Cij=Ci1j1+Ci1j预处理 C C C k k k取模的结果
用二维前缀和保存其为0的情况即可

时间复杂度: O ( n 2 + T ) O(n^2+T) O(n2+T)


C o d e Code Code
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;int T,n,m,k,C[2010][2010],s[2010][2010];
inline LL read()
{
	char c;LL d=1,f=0;
	while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
signed main()
{
	T=read();k=read();
	C[0][0]=1;C[1][0]=1;C[1][1]=1;
	for(register int i=2;i<=2000;i++)
	{
		C[i][0]=1;
		for(register int j=1;j<=i;j++)
		{
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%k;
			s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+(C[i][j]==0);
		}
		s[i][i+1]=s[i][i];
	}
	while(T--)
	{
		n=read();m=read();
		if(m<=n) printf("%d\n",s[n][m]);
		else printf("%d\n",s[n][n]);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值