題目鏈接
題目大意
組詢問, 每組詢問問 .
數據範圍
解題思路
定義 .
由楊輝三角的遞推公式 可以推導出
這樣我們就可以得到下面四個轉移公式:
即使這樣可以 的轉移, 但是最壞也是需要 的複雜度, 沒辦法實現。
這時候就可以把 和 看成區間 和 。 使用莫隊算法處理一下。 以前沒寫過莫隊, 正好趁這次機會學會了莫隊算法。
使用莫隊, 將 分成 塊, 按照 所在的塊從小到大排序, 對於同一塊內, 按照 從小到大排序。
這樣的話可以使複雜度降到 。
簡單證明(現學現賣):
- 對於同一塊內, 最多移動 , 最多移動 次,總共有 塊, 所以這種情況的複雜度爲
- 對不在同一塊內的, 最多移動 次, 還是移動 次, 所以還是
AC代碼
/********************************************
*Author* :ZZZZone
*Created Time* : 日 8/ 5 14:48:44 2018
* Ended Time* : 日 8/ 5 15:24:14 2018
* 莫隊算法
*********************************************/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
#define debug(x) std::cerr << #x << " = " << (x) << std::endl
typedef pair<int, int> PII;
typedef long long LL;
typedef unsigned long long ULL;
inline void OPEN(string s){
freopen((s + ".in").c_str(), "r", stdin);
freopen((s + ".out").c_str(), "w", stdout);
}
const int MAXN = 1e5;
const int Mod = 1e9 + 7;
LL fac[MAXN+5], rfac[MAXN+5], Ans[MAXN+5];
int blk[MAXN+5];
int n, Block;
struct Query{
int l, r, id;
bool operator < (const Query& tmp) const{
if(blk[l] == blk[tmp.l]) return r < tmp.r;
return blk[l] < blk[tmp.l];
}
}Q[MAXN+5];
LL fast_pow(LL x, LL y){
LL res = 1LL;
while(y != 0LL){
if(y & 1) res = (res * x) % Mod;
y >>= 1;
x = x * x % Mod;
}
return res;
}
inline LL Comb(LL N, LL M){
if(N<M)return 0LL; // ****** 一定不能忘 ****** //
return fac[N] * rfac[M] % Mod * rfac[N-M] % Mod;
}
void Init(){
fac[0] = 1LL;
for(int i = 1; i <= MAXN; i++) fac[i] = fac[i-1] * (LL)i % Mod;
for(int i = 0; i <= MAXN; i++){
rfac[i] = fast_pow(fac[i], Mod - 2LL);
blk[i] = i / Block;
}
for(int i = 1; i <= n; i++) scanf("%d %d", &Q[i].r, &Q[i].l), Q[i].id = i;
sort(Q + 1, Q + 1 + n);
}
int main()
{
scanf("%d", &n);
Block = sqrt(n);
Init();
int L = 1, R = 0;
LL ans = 1LL;
for(int i = 1; i <= n; i++){
while(L < Q[i].l){
L++;
ans = (ans + Comb(R, L)) % Mod;
}
while(L > Q[i].l){
ans = (ans - Comb(R, L) + Mod) % Mod;
L--;
}
while(R < Q[i].r){
ans = (2LL * ans % Mod - Comb(R, L) + Mod) % Mod;
R++;
}
while(R > Q[i].r){
R--;
ans = (ans + Comb(R, L)) % Mod * rfac[2] % Mod;
}
Ans[Q[i].id] = ans % Mod;
}
for(int i = 1; i <= n; i++) printf("%lld\n", Ans[i]);
return 0;
}