【洛谷P4345】超能粒子炮·改

题目

题目链接:https://www.luogu.com.cn/problem/P4345
曾经发明了脑洞治疗仪与超能粒子炮的发明家 SHTSC 又公开了他的新发明:超能粒子炮・改——一种可以发射威力更加强大的粒子流的神秘装置。
超能粒子炮・改相比超能粒子炮,在威力上有了本质的提升。它有两个参数 \(n,k\) ,它会向每个编号为 \(0\)\(k\) (包含两端)的位置 \(i\) 发射威力为 \(C_{n}^{i} \bmod 2333\) 的粒子流。
现在 SHTSC 给出了他的超能粒子炮・改的参数,让你求出其发射的粒子流的威力之和除以 \(2333\) 所得的余数。
\(t \leq 100000,n,k \le 10^{18}\)

思路

约定以下以下所有除法均为整除(下取整)。
题目所求为

\[f_{n,k}=\sum^{k}_{i=0}\binom{n}{i}=\sum^{k}_{i=0}\binom{n\div p}{i\div p}\binom{n\bmod p}{i\bmod p} \]

看见除法不难想到整除分块

\[=\left(\sum^{p-1}_{i=0}\binom{n\div p}{i}\right)\left(\sum_{i=0}^{k\div p-1}\binom{n\div p}{i}\right)+\binom{n\div p}{k\div p}\left(\sum^{k\bmod p}_{i=0}\binom{n\bmod p}{i}\right) \]

\(g_{i,j}=\sum^{j}_{k=0}\binom{k}{i}\)

\[=g_{n\bmod p,p-1}f_{n\div p,k\div p-1}+\binom{n\div p}{k\div p}g_{n\bmod p,k\bmod p} \]

因为下标全部小于 \(p\),所以 \(g\) 可以预处理出来,然后组合数用 Lucas 求,\(f\) 递归求即可。
时间复杂度 \(O(p^2+Q\log^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\n",calc(a,b));
	}
	return 0;
}
posted @ 2021-01-26 11:42  stoorz  阅读(107)  评论(0编辑  收藏  举报