BZOJ-4591 超能粒子炮·改(lucas定理+预处理)
2016-08-03 11:18
471 查看
题意:求[C(n,0)+C(n,1)+...+C(n,k)]%2333的值。
分析:因为n和k的值太大,不能直接预处理组合数,由lucas定理:C(n,k)%mod=C(n/mod,k/mod)*C(n%mod,k%mod)%mod,可得到如下结果
便于说明,记[C(n%mod,0)+C(n%mod,1)+...+C(n%mod,mod-1)]%mod=∑C(n%mod,0~mod-1)
ans(n,k)=[C(n,0)+C(n,1)+...+C(n,k)]%mod=C(n/mod,0)*∑C(n%mod,0~mod-1)%mod+C(n/mod,1)*∑C(n%mod,0~mod-1)%mod+...+C(n/mod,k/mod-1)*∑C(n%mod,0~mod-1)%mod+C(n/mod,k/mod)*∑C(n%mod,0~k%mod)%mod=∑C(n/mod,0~k/mod-1)*∑C(n%mod,0~mod-1)+C(n/mod,k/mod)*∑C(n%mod,0~k%mod);
即ans(n,k)=∑C(n/mod,0~k/mod-1)*∑C(n%mod,0~mod-1)+C(n/mod,k/mod)*∑C(n%mod,0~k%mod);
对于n%mod以内的组合数及前缀和可以预处理得到,大组合数可以用lucas定理求解,并且∑C(n/mod,0~k/mod-1)=ans(n/mod,k/mod-1),所以可以采取递归的方法求解最终结果,有如下递归式:
ans(n,k)=ans(n/mod,k/mod-1)*sum[n%mod][mod-1]+lucas(n/mod,k/mod)*sum[n%mod][k%mod];
分析:因为n和k的值太大,不能直接预处理组合数,由lucas定理:C(n,k)%mod=C(n/mod,k/mod)*C(n%mod,k%mod)%mod,可得到如下结果
便于说明,记[C(n%mod,0)+C(n%mod,1)+...+C(n%mod,mod-1)]%mod=∑C(n%mod,0~mod-1)
ans(n,k)=[C(n,0)+C(n,1)+...+C(n,k)]%mod=C(n/mod,0)*∑C(n%mod,0~mod-1)%mod+C(n/mod,1)*∑C(n%mod,0~mod-1)%mod+...+C(n/mod,k/mod-1)*∑C(n%mod,0~mod-1)%mod+C(n/mod,k/mod)*∑C(n%mod,0~k%mod)%mod=∑C(n/mod,0~k/mod-1)*∑C(n%mod,0~mod-1)+C(n/mod,k/mod)*∑C(n%mod,0~k%mod);
即ans(n,k)=∑C(n/mod,0~k/mod-1)*∑C(n%mod,0~mod-1)+C(n/mod,k/mod)*∑C(n%mod,0~k%mod);
对于n%mod以内的组合数及前缀和可以预处理得到,大组合数可以用lucas定理求解,并且∑C(n/mod,0~k/mod-1)=ans(n/mod,k/mod-1),所以可以采取递归的方法求解最终结果,有如下递归式:
ans(n,k)=ans(n/mod,k/mod-1)*sum[n%mod][mod-1]+lucas(n/mod,k/mod)*sum[n%mod][k%mod];
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int mod=2333; ll c[mod+5][mod+5];//记录组合数 ll sum[mod+5][mod+5];//保存前缀和 void pre() //预处理求出n%mod以内的组合数和前缀和 { for(int i=0;i<=mod;i++) sum[0][i]=1; c[0][0]=1; for(int i=1;i<=mod;i++) { c[i][0]=sum[i][0]=1; for(int j=1;j<=i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod; for(int j=1;j<=mod;j++) sum[i][j]=(sum[i][j-1]+c[i][j])%mod; } } int lucas(ll n,ll m) { if(n==0||m==0) return 1; return lucas(n/mod,m/mod)*c[n%mod][m%mod]%mod; } int solve(ll n,ll k) { if(k<0) return 0; return (solve(n/mod,k/mod-1)*sum[n%mod][mod-1]%mod+lucas(n/mod,k/mod)*sum[n%mod][k%mod]%mod)%mod; } int main() { pre(); int T; cin>>T; while(T--) 4000 { ll n,k; scanf("%lld%lld",&n,&k);//注意不能用I64d,之前用了wa了好几发。。。 int ans=solve(n,k); printf("%d\n",ans); } return 0; }
相关文章推荐
- 【bzoj4591】【Shoi2015超能粒子炮·改】【lucas定理】
- bzoj 4591: [Shoi2015]超能粒子炮·改 (Lucas定理)
- bzoj 4591: [Shoi2015]超能粒子炮·改 Lucas定理+组合数学
- 【bzoj4591】[Shoi2015]超能粒子炮·改 Lucas定理
- bzoj 4591: [Shoi2015]超能粒子炮·改 [lucas定理]
- Bzoj 4591: [Shoi2015]超能粒子炮·改 数论,Lucas定理,排列组合
- 【BZOJ4591】[Shoi2015]超能粒子炮·改 Lucas定理
- [bzoj4591][Shoi2015][超能粒子炮·改] (lucas定理+组合计数)
- [BZOJ4591][SHOI2015]超能粒子炮·改(Lucas定理+数位DP)
- BZOJ_4591_[Shoi2015]超能粒子炮·改_Lucas定理
- bzoj 4591: [Shoi2015]超能粒子炮·改
- 【BZOJ4591】超能粒子炮·改(Lucas定理,组合计数)
- 【BZOJ-4591】超能粒子炮·改 数论 + 组合数 + Lucas定理
- BZOJ4591 [Shoi2015]超能粒子炮·改
- 【bzoj4591】[Shoi2015]超能粒子炮·改 Lucas定理
- 【BZOJ4591】 SHOI2015 超能粒子炮·改
- 【SHOI2015】bzoj4591 超能粒子炮·改
- BZOJ4591 SHOI2015超能粒子炮·改(卢卡斯定理+数位dp)
- 【bzoj4591】[Shoi2015]超能粒子炮·改
- bzoj 4591 [Shoi2015]超能粒子炮·改