bzoj4591超能粒子炮·改
Posted yoyoball
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4591超能粒子炮·改相关的知识,希望对你有一定的参考价值。
Solution
首先这个模数是一个质数
然后看一下那个(k)和(n)的范围。。行吧Lucas定理咯
但是如果直接求:
[
sumlimits_{i=0}^{k}inom n i
]
那。。稳稳的T啊。。。所以要化一下式子,我们令(k=ap+b):
[
egin{aligned}
sumlimits_{i=0}^{k}inom n i&equiv sumlimits_{i=0}^k inom {i/p} {n/p}inom {i\% p}{n\%p}(mod p)&equiv sumlimits_{i=0}^{ap-1}inom {i/p} {n/p}inom {i\% p}{n\%p}+sumlimits_{i=ap}^{ap+b}inom {i/p} {n/p}inom {i\% p}{n\%p}(mod p)&equiv sumlimits_{i=0}^{a-1}inom {i} {n/p}sumlimits_{i=0}^{p-1}inom {i}{n\%p}+inom a {n/p}sumlimits_{i=0}^binom {i}{n\%p}
end{aligned}
]
然后因为(p)比较小(只有(2333)真是2333)
所以我们可以直接暴力处理出(n,m<=2333)的(inom n m)的的前缀和
然后对于范围内的直接调用,范围外的用上面那个式子递归处理就好了
代码大概长这个样子:
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int MOD=2333;
ll c[MOD+10][MOD+10],sum[MOD+10][MOD+10];
ll n,k,T,ans;
void prework(int n);
ll Lucas(ll n,ll m);
ll Min(ll x,ll y){return x<y?x:y;}
ll f(ll n,ll k);
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
ll a,b;
scanf("%lld",&T);
prework(MOD);
for (int o=1;o<=T;++o){
scanf("%lld%lld",&n,&k);
printf("%lld
",f(n,k));
}
}
void prework(int n){
c[0][0]=1;
for (int i=1;i<=n;++i){
c[i][0]=1; c[i][i]=1;
for (int j=1;j<i;++j)
c[i][j]=(c[i-1][j-1]+c[i-1][j])%MOD;
}
for (int i=0;i<=n;++i){
sum[i][0]=c[i][0];
for (int j=1;j<=n;++j)
sum[i][j]=(sum[i][j-1]+c[i][j])%MOD;
}
}
ll Lucas(ll n,ll m){
if (n<m) return 0;
if (n<MOD&&m<MOD) return c[n][m];
return c[n%MOD][m%MOD]*Lucas(n/MOD,m/MOD)%MOD;
}
ll f(ll n,ll k){
if (k<0) return 0;
if (n<MOD&&k<MOD) return sum[n][k];
return (f(n/MOD,min(k/MOD-1,n/MOD))*sum[n%MOD][MOD-1]%MOD+Lucas(n/MOD,k/MOD)*sum[n%MOD][k%MOD]%MOD)%MOD;
}
以上是关于bzoj4591超能粒子炮·改的主要内容,如果未能解决你的问题,请参考以下文章
bzoj4591[Shoi2015]超能粒子炮·改 Lucas定理
BZOj-4591: [Shoi2015]超能粒子炮·改 (Lucas+排列组合)