题目
题目链接:https://www.luogu.com.cn/problem/P4345
曾经发明了脑洞治疗仪与超能粒子炮的发明家 SHTSC 又公开了他的新发明:超能粒子炮・改——一种可以发射威力更加强大的粒子流的神秘装置。
超能粒子炮・改相比超能粒子炮,在威力上有了本质的提升。它有两个参数 (n,k) ,它会向每个编号为 (0) 到 (k) (包含两端)的位置 (i) 发射威力为 (C_{n}^{i} mod 2333) 的粒子流。
现在 SHTSC 给出了他的超能粒子炮・改的参数,让你求出其发射的粒子流的威力之和除以 (2333) 所得的余数。
(t leq 100000,n,k le 10^{18})。
思路
约定以下以下所有除法均为整除(下取整)。
题目所求为
[f_{n,k}=sum^{k}_{i=0}inom{n}{i}=sum^{k}_{i=0}inom{ndiv p}{idiv p}inom{nmod p}{imod p}
]
看见除法不难想到整除分块
[=left(sum^{p-1}_{i=0}inom{ndiv p}{i}
ight)left(sum_{i=0}^{kdiv p-1}inom{ndiv p}{i}
ight)+inom{ndiv p}{kdiv p}left(sum^{kmod p}_{i=0}inom{nmod p}{i}
ight)
]
令 (g_{i,j}=sum^{j}_{k=0}inom{k}{i})
[=g_{nmod p,p-1}f_{ndiv p,kdiv p-1}+inom{ndiv p}{kdiv p}g_{nmod p,kmod p}
]
因为下标全部小于 (p),所以 (g) 可以预处理出来,然后组合数用 Lucas 求,(f) 递归求即可。
时间复杂度 (O(p^2+Qlog^2 n))。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll p=2333;
int Q;
ll a,b,C[p][p],g[p][p];
ll lucas(ll n,ll m)
{
if (n<p && m<p) return C[n][m];
return lucas(n/p,m/p)*C[n%p][m%p]%p;
}
ll calc(ll n,ll k)
{
if (k<0) return 0;
if (n<p && k<p) return g[n][k];
return (g[n%p][p-1]*calc(n/p,k/p-1)+lucas(n/p,k/p)*g[n%p][k%p])%p;
}
int main()
{
for (int i=0;i<p;i++)
C[i][0]=g[i][0]=g[0][i]=1;
for (int i=1;i<p;i++)
for (int j=1;j<p;j++)
{
C[i][j]=(C[i-1][j]+C[i-1][j-1])%p;
g[i][j]=(C[i][j]+g[i][j-1])%p;
}
scanf("%d",&Q);
while (Q--)
{
scanf("%lld%lld",&a,&b);
printf("%lld
",calc(a,b));
}
return 0;
}