您的位置:首页 > 其它

洛谷2822 组合数问题

2017-08-22 07:25 176 查看

来源

NOIP 2016 提高组 D2T1

题目描述

(公式太难打,自己看原题吧)

传送门

算法

暴力

50分拿好。。。

递推

注意到组合数的递推公式:

c[i][j]=c[i−1][j]+c[i−1][j−1]

所以我们可以先把c表打出来,记得%k

然后判断这个数是否能被k整除,是的话就统计;

然后记录下(输入为i、j)的答案。

然后对于输入,直接输出即可。

代码

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef unsigned long long LL;
LL s[2010][2010],c[2010][2010]; //s[i][j]表示前i行j列有多少个j的约数
LL h[2010]; //第i行有多少个k的约数
int main()
{
int t,k,n,m;
scanf("%d%d",&t,&k);
c[0][0]=1; //边界:C(0,0)=1;
for (int i=1;i<=2001;i++)
{
c[i][0]=1; //边界:C(i,0)=1
for (int j=1;j<=i;j++)
{
c[i][j]=(c[i-1][j]+c[i-1][j-1])%k; //递推
if (c[i][j]%k==0) h[i]++; //处理约数
s[i][j]=s[i-1][j]+h[i]; //累加s[i][j]
if (i==j) s[i][j]=s[i-1][j-1]+h[i]; //这里要特判
}
}
while (t--)
{
scanf("%d%d",&n,&m);
if (m>n) m=n; //注意特判
printf("%d\n",s
[m]);
}
return 0;
}


后记

这道题考到了组合数的递推公式,是一道不错的数论题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: