洛谷-4345 [SHOI2015]超能粒子炮·改

题目描述
曾经发明了脑洞治疗仪与超能粒子炮的发明家 SHTSC 又公开了他的新发明:超能粒子炮・改——一种可以发射威力更加强大的粒子流的神秘装置。
超能粒子炮・改相比超能粒子炮,在威力上有了本质的提升。它有两个参数n,k,它会向每个编号为0到k(包含两端)的位置iii发射威力为 C n i m o d 2333 C_{n}^{i} mod 2333 Cnimod2333的粒子流。
现在 SHTSC 给出了他的超能粒子炮・改的参数,让你求出其发射的粒子流的威力之和除以2333所得的余数。
输入格式
第一行一个整数 t表示数据组数。 之后 t 行,每行两个整数 n、k,含义如题面描述。
输出格式
t 行,每行一个整数,表示其粒子流的威力之和模 2333 的值。

输入输出样例
输入 #1
3
5 5
10 7
1145 14

输出 #1
32
968
763

说明/提示
在这里插入图片描述

解释:卢卡斯定理, C n k m o d    p = C n / p k / p ∗ C n m o d    p k m o d    p C_n^k \mod p=C_{n/p}^{k/p}*C^{k\mod p}_{n\mod p} Cnkmodp=Cn/pk/pCnmodpkmodp
我们设 f ( n , k ) = ∑ i = 0 k C n i = ∑ i = 0 k k C n p i ∗ ( ∑ j = 0 p − 1 C n m o d    p j ) f(n,k)=\sum_{i=0}^kC_{n}^i=\sum_{i=0}^{\frac{k}{k}}C_{\frac{n}{p}}^i*(\sum_{j=0}^{p-1}C_{n \mod p}^j) f(n,k)=i=0kCni=i=0kkCpni(j=0p1Cnmodpj)
= ∑ i = 0 k p − 1 C n p i ∗ ( ∑ j = 0 p − 1 C n m o d    p j ) + C n p k p ∗ ( ∑ n p k p C n m o d    p j ) =\sum_{i=0}^{\frac{k}{p}-1}C_{\frac{n}{p}}^i*(\sum_{j=0}^{p-1}C_{n \mod p}^j)+C_{\frac{n}{p}}^{\frac{k}{p}}*(\sum_{\frac{n}{p}}^{\frac{k}{p}}C_{n \mod p}^j) =i=0pk1Cpni(j=0p1Cnmodpj)+Cpnpk(pnpkCnmodpj)
= f ( n m o d    p , p − 1 ) ∗ f ( n p , k p − 1 ) + C n m o d    p k m o d    p ∗ f ( n m o d    p , k m o d    p ) =f(n \mod p,p-1)*f(\frac{n}{p},\frac{k}{p}-1)+C_{n \mod p}^{k \mod p}*f(n \mod p,k \mod p) =f(nmodp,p1)f(pn,pk1)+Cnmodpkmodpf(nmodp,kmodp)
然后我们分块就可以啦

#include<iostream>
#define mod 2333
using namespace std;
typedef long long ll;
ll C[2335][2335]={0};
ll F[2335][2335]={0};
ll Lucas(ll n,ll m){
    if(!m) return 1;
    if(n==m) return 1;
    if(n<m) return 0;
    return C[n%mod][m%mod]*Lucas(n/mod,m/mod)%mod;
}
ll f(ll n,ll k){
    if(k<0) return 0LL;
    if(k==0) return 1LL;
    if(n==0) return 1LL;
    if(n<=mod&&k<=mod) return F[n][k];
    return (F[n%mod][mod-1]*f(n/mod,k/mod-1)%mod+Lucas(n/mod,k/mod)*F[n%mod][k%mod]%mod)%mod;
}
int main(){
    ios::sync_with_stdio(false);
    C[0][0]=1;
    for(int i=1;i<=2333;i++){
        C[i][0]=1;
        for(int j=1;j<=i;j++){
            C[i][j]=C[i-1][j-1]+C[i-1][j];
            C[i][j]%=mod;
        }
    }
    F[0][0]=1;
    for(int i=0;i<=2333;i++){
        F[i][0]=1;
        for(int j=1;j<=2333;j++){
            F[i][j]+=F[i][j-1]+C[i][j];
            F[i][j]%=mod;
        }
    }
    int T=0;cin>>T;
    while(T--){
        ll n,k;
        cin>>n>>k;
        cout<<f(n,k)<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值