题意:
给定
n,m
n
,
m
,求出
∑mi=0Cin
∑
i
=
0
m
C
n
i
,一共有
1e5
1
e
5
组询问。
思路:
记
则结合杨辉三角,可得:
故可以直接使用莫队算法来解决该题,时间复杂度 O(nn−−√) O ( n n )
也可以直接分块,因为 n,m≤1e5 n , m ≤ 1 e 5 ,故所有的 F F 共有个数,因为每一个维度的 +1/−1 + 1 / − 1 均可以 O(1) O ( 1 ) 推出,所以可以直接对 n n 分块,假定块的大小为,则时间复杂度为: O(n∗m/nuit) O ( n ∗ m / n u i t )
此题得解。
代码:
莫队算法:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int A = 1e5 + 10;
int fac[A], Inv[A], Ans[A], block, T;
ll res;
class Que{
public:
int L, R, id;
bool operator<(const Que& rhs) const{
if(L/block == rhs.L/block) return R < rhs.R;
return L/block < rhs.L/block;
}
}Q[A];
int Mul(ll a, int b){
a *= b;
return a >= mod?a%mod:a;
}
int Add(int a, int b){
a += b;
return a >= mod?a-mod:a;
}
int Sub(int a, int b){
a -= b;
return a < 0?a+mod:a;
}
int fast_mod(int n, int m){
int res = 1;
while(m > 0){
if(m&1) res = Mul(res, n);
n = Mul(n, n);
m >>= 1;
}
return res;
}
int Comb(int n, int m){
return Mul(Mul(fac[n], Inv[m]), Inv[n-m]);
}
void Init(){
fac[0] = Inv[0] = 1;
for (int i = 1; i < A; i++) fac[i] = Mul(fac[i-1],i);
Inv[A-1] = fast_mod(fac[A-1], mod - 2);
for (int i = A-2; i>=1; i--) Inv[i] = Mul(Inv[i+1], i + 1);
}
void solve(){
int l = 1, r = 0;
res = 1;
for (int i = 1; i <= T; i++) {
while (r < Q[i].R) {
r++;
res = Sub(Mul(res, 2), Comb(r - 1, l));
}
while (l > Q[i].L) {
res = Sub(res, Comb(r, l));
l--;
}
while (r > Q[i].R) {
res = Mul(Add(res, Comb(r - 1, l)), Inv[2]);
r--;
}
while (l < Q[i].L) {
l++;
res = Add(res, Comb(r, l));
}
Ans[Q[i].id] = res;
}
for (int i = 1; i <= T; i++) printf("%d\n", Ans[i]);
}
int main(){
Init();
scanf("%d",&T);
block = 0;
for (int i = 1; i <= T; i++) {
Q[i].id = i;
scanf("%d%d", &Q[i].R, &Q[i].L);
block = max(block, Q[i].R);
}
block = (int)sqrt(1.0 * block);
sort(Q + 1, Q + 1 + T);
solve();
return 0;
}
对 n n 分块:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int A = 1e5 + 1000;
const int B = A/500 + 100;
int fac[A], Inv[A];
int a[B][A], tem[2][A];
int Mul(ll a, int b){
a *= b;
return a >= mod?a%mod:a;
}
int Add(int a, int b){
a += b;
return a >= mod?a-mod:a;
}
int Sub(int a, int b){
a -= b;
return a < 0?a+mod:a;
}
int fast_mod(int n, int m){
int res = 1;
while(m > 0){
if(m&1) res = Mul(res, n);
n = Mul(n, n);
m >>= 1;
}
return res;
}
int Comb(int n, int m){
return Mul(Mul(fac[n], Inv[m]), Inv[n-m]);
}
void Init(){
fac[0] = Inv[0] = 1;
for (int i = 1; i < A; i++) fac[i] = Mul(fac[i-1],i);
Inv[A-1] = fast_mod(fac[A-1], mod - 2);
for (int i = A-2; i>=1; i--) Inv[i] = Mul(Inv[i+1], i + 1);
for (int i = 0; i < A; i += 500) {
a[i/500][0] = 1;
for (int j = 1; j <= i; j++) a[i/500][j] = Add(a[i/500][j-1], Comb(i,j));
}
}
int main(){
Init();
int T, n, m, res;
scanf("%d",&T);
while(T--){
scanf("%d%d", &n, &m);
n++;
res = 0;
res = a[(n/500)+1][m];
for (int i = ((n/500)+1)*500; i >= n; i--){
res = Mul(Add(res,Comb(i-1,m)), Inv[2]);
}
printf("%d\n", res);
}
return 0;
}