luogu2822 组合数问题
Posted headboy2002
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu2822 组合数问题相关的知识,希望对你有一定的参考价值。
题目大意:给定$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 组合数问题的主要内容,如果未能解决你的问题,请参考以下文章