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

$Noip2016/Luogu2822$ 组合数问题

时间:2019-08-24 22:33:42      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:color   com   pac   long   opened   names   查询   namespace   show   

$Luogu$

 

看这题题解的时候看到一个好可爱的表情(●‘?‘●)?♥

 

$Sol$

首先注意到这题的模数是$k$.然而$k$并不一定是质数,所以不能用$C_n^m=\frac{n!}{m!(n-m)!}$.

所以还要记得另外一个公式吖:$C_n^m=C_{n-1}^{m}+C_{n-1}^{m-1}$

于是可以预处理出所有的$C$,以及所有的前缀和.这样就可以$O(1)$查询了.

最后还要注意特判$m>n$的情况

$over$

 

$Code$

 

技术图片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define il inline
#define Rg register
#define go(i,a,b) for(Rg int i=a;i<=b;++i)
#define yes(i,a,b) for(Rg int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define db double
#define inf 2147483647
using namespace std;
il int read()
{
    Rg int x=0,y=1;char c=getchar();
    while(c<0||c>9){if(c==-)y=-1;c=getchar();}
    while(c>=0&&c<=9){x=(x<<1)+(x<<3)+c-0;c=getchar();}
    return x*y;
}
const int N=2010;
int T,k,n,m,c[N][N];
ll s[N][N];
il void init()
{
    c[1][1]=1;
    go(i,1,2000)c[i][0]=1;
    go(i,2,2000)
        go(j,1,i)
    {
        c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;
        if(!c[i][j])s[i][j]=1;
    }
    go(i,2,2000)
    {
        go(j,1,i)s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
        s[i][i+1]=s[i][i];
    }
}
int main()
{
    T=read();k=read();init();
    while(T--)
    {
        n=read(),m=read();
        if(m>n)m=n;
        printf("%lld\n",s[n][m]);
    }
    return 0;
}
View Code

 

 

 

$Noip2016/Luogu2822$ 组合数问题

标签:color   com   pac   long   opened   names   查询   namespace   show   

原文地址:https://www.cnblogs.com/forward777/p/11406082.html

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