bzoj4591 【Shoi2015】超能粒子炮·改

由Lucas定理C(n,k)=C(n/2333,k/2333)*C(n%2333,k%2333)%2333

则ans=ΣC(n,i),(i<=k)

    =C(n/2333,0)*C(n%2333,0)+C(n/2333,0)*C(n%2333,1)+...+C(n/2333,0)*C(n%2333,2332)

    +C(n/2333,1)*C(n%2333,0)+C(n/2333,1)*C(n%2333,1)+...+C(n/2333,1)*C(n%2333,2332)

    +.....

    +C(n/2333,k/2333)*C(n%2333,0)+....+C(n/2333,k/2333)*C(n%2333,k%2333)

    =∑C(n/2333,j)*sum[n%2333][2332]+C(n/2333,k/2333)*sum[n%2333][k%2333],(0<=j<k/2333)

cal(n,k)=cal(n/2333,k/2333-1)*sum[n%2333][2332]+Lucas(n/2333,k/2333)*sum[n%2333][k%2333]

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define int long long
using namespace std;
const int p=2333;
int T,c[p+10][p+10],sum[p+10][p+10];
int Lucas(int a,int b)
{
    if(a<0||b<0) return 0;
    if(a<p&&b<p) return c[a][b];
    return Lucas(a/p,b/p)*c[a%p][b%p]%p;
}
int cal(int n,int k)
{
    if(k<0) return 0;
    return (cal(n/p,k/p-1)*sum[n%p][p-1]+Lucas(n/p,k/p)*sum[n%p][k%p])%p;
}
void pre()
{
    c[0][0]=1;sum[0][0]=1; for(int i=1;i<p;i++) c[i][0]=1,sum[i][0]=1,sum[0][i]=1;
    for(int i=1;i<p;i++) for(int j=1;j<=i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%p;
    for(int i=1;i<p;i++) for(int j=1;j<p;j++) sum[i][j]=sum[i][j-1]+c[i][j];
}
signed main()
{
    pre();
    scanf("%lld",&T);
    while(T--)
    {
        int n,k;
        scanf("%lld%lld",&n,&k);
        printf("%lld\n",cal(n,k));
    }
    return 0;
}

 

posted @ 2016-12-12 11:52  Czarina  阅读(316)  评论(0编辑  收藏  举报