[SHOI2015] 超能粒子炮·改

题目链接:戳我

\(f[n][k]=\sum_{i=0}^kC_n^i\pmod {2333}\)
那么根据卢卡斯定理我们知道\(f[n][k]=\sum_{i=0}^kC_{n/p}^{i/p}\times C_{n\%p}^{i\%p}\)

\(=C_{n/p}^0\times \sum_{i=0}^{p-1}C_{n\%p}^i+C_{n/p}^1\times \sum_{i=0}^{p-1}C_{n\%p}^i+...+C_{n/p}^{k/p-1}\times \sum_{i=0}^{p-1}C_{n\%p}^i+C_{n/p}^{k/p}\times \sum_{i=0}^{k\%p}C_{n\%p}^i\)

\(=\sum_{i=0}^{p-1}C_{n\%p}^i\times(C_{n/p}^0+C_{n/p}^1+...+C_{n/p}^{k/p-1})+\sum_{i=0}^{k\%p}C_{n\%p}^i\)

\(=\sum_{i=0}^{p-1}C_{n\%p}^i\times \sum_{j=1}^{k/p-1}C_{n/p}^j+\sum_{i=0}^{k\%p}C_{n\%p}^i\)

\(=f[n\%p][p-1]\times f[n/p][k/p-1]+C_{n/p}^{k/p}\times f[n\%p][k\%p]\)

取模的那些我们可以先预处理出来(小于等于2333),然后除法操作的那些我们递归计算即可。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define p 2333
using namespace std;
int T;
ll n,k;
ll c[2500][2500],f[2500][2500];
inline void init()
{
    c[0][0]=1;
	for(int i=1;i<=2333;i++)
        c[i][0]=c[i][i]=1;	
    for(int i=1;i<=2333;i++)
        for(int j=1;j<i;j++)
            c[i][j]=(c[i-1][j-1]+c[i-1][j])%p;
}
inline ll lucas(ll down,ll up)
{
    if(down==up||up==0) return 1;
    if(down<up) return 0;
    return lucas(down/p,up/p)*c[down%p][up%p]%p;
}
inline ll F(ll down,ll up)
{
    if(!down||!up) return 1;
    if(up<0||down<0) return 0;
    if(down<2333&&up<2333) return f[down][up];
    return (f[down%p][p-1]*F(down/p,up/p-1)%p+lucas(down/p,up/p)*f[down%p][up%p]%p)%p;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    scanf("%d",&T);
    init();
    f[0][0]=1;
    for(int i=1;i<=2333;i++) f[i][0]=1;
    for(int i=0;i<=2333;i++) 
        for(int j=1;j<=2333;j++)
            f[i][j]=(f[i][j-1]+c[i][j])%p;
    while(T--)
    {
        scanf("%lld%lld",&n,&k);
        printf("%lld\n",F(n,k));
    }
    return 0;
}
posted @ 2019-02-22 20:06  风浔凌  阅读(301)  评论(1编辑  收藏  举报