码迷,mamicode.com
首页 > 其他好文 > 详细

luogu2822 组合数问题

时间:2018-05-06 00:14:04      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:find   algorithm   define   ||   efi   time   sum   void   ret   

题目大意:给定$n,m,k$,对于所有的$0\leq i\leq n,0\leq j\leq \min(i,m)$有多少对$(i,j)$满足$k|C_{i}^{j}$。

题解:预处理,在运用$C_{n}^{m}=C_{n-1}^{m-1}+C_{n-1}^{m}$求组合数的过程中顺便求一下$f(n,m)=|\{i|i\in [0,m]且k|C_{n}^{i}\}|$。每次询问,运用循环求$\sum_{i=0}^{n}f(i,\min(i,m))$即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <ctime>
using namespace std;

#define ll long long

const int MAX_N = 2010, MAX_M = 2010;
int Prifix[MAX_N][MAX_M];
int K;

void SetPrifix(int n, int m)
{
	static int C[MAX_N];
	C[0] = 1;
	Prifix[0][0] = 0;
	for (int i = 1; i <= n; i++)
	{
		for (int j = min(i, m); j >= 0; j--)
		{
			if (i == j || j == 0)
				C[j] = 1;
			else
				C[j] = (C[j - 1] + C[j]) % K;
		}
		Prifix[i][0] = (C[0] == 0);
		for (int j = 1; j <= min(i, m); j++)
			Prifix[i][j] = Prifix[i][j - 1] + (C[j] == 0);
	}
}

int Find(int n, int m)
{
	int ans = 0;
	for (int i = 1; i <= n; i++)
		ans += Prifix[i][min(i, m)];
	return ans;
}

int main()
{
	int caseCnt, n, m;
	scanf("%d%d", &caseCnt, &K);
	SetPrifix(2000, 2000);
	while (caseCnt--)
	{
		scanf("%d%d", &n, &m);
		printf("%d\n", Find(n, m));
	}
	return 0;
}

  

luogu2822 组合数问题

标签:find   algorithm   define   ||   efi   time   sum   void   ret   

原文地址:https://www.cnblogs.com/headboy2002/p/8996677.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!