B
S(n,m) = S(n,m-1) + C(n,m)
S(n,m) = 2 * S(n-1,m) - C (n-1,m)
这个式子可由杨辉三角得出:上面一行的相邻两个元素相加得下面的元素,那么下面元素的和就是上面一行和的2倍减去上一行最后一个元素,因为它对下面一行只贡献了一次。
由上两个式子可得:
S(n,m) = S(n,m+1) + C(n,m+1)
S(n+1,m) = 2 * S(n,m) - C(n,m)
那么知道S(n,m),并且预处理逆元与阶乘就可O(1)求出。
#include
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 3e5+66;
const int MOD = 1e9+7;
const int MAX = 1e5;
int b[AX];
int fac[AX];
int inv[AX];
int res[AX];
struct Node{
int l , r ;
int id ;
/* bool friend operator < ( const Node &x , const Node &y ){
return ( b[x.l] == b[y.l] ? x.r < y.r : b[x.l] < b[y.l] );
}*/
}s[AX];
bool cmp( Node a , Node b ){
return a.r < b.r;
}
int quick( int a , int b ){
int ans = 1 ;
while( b ){
if( b & 1 ){
ans = ( 1LL * ans * a ) % MOD;
}
b >>= 1 ;
a = ( 1LL * a * a ) % MOD;
}
return ans ;
}
int C(int a, int b){
return 1ll * fac[a] * inv[b] % MOD * inv[a - b] % MOD;
}
std::vector v[AX];
int main(){
int T;
fac[0] = 1;
for( int i = 1 ; i <= MAX ; i++ ){
fac[i] = 1LL * fac[i-1] * i % MOD ;
}
inv[MAX] = quick( fac[MAX] , MOD - 2 );
for( int i = MAX - 1 ; ~i ; i-- ){
inv[i] = 1LL * inv[i+1] * ( i + 1 ) % MOD;
}
scanf("%d",&T);
int len = sqrt(MAX);
for( int i = 1 ; i <= MAX ; i++ ){
b[i] = ( i - 1 ) / len + 1 ;
}
for( int i = 1 ; i <= T ; i ++ ){
scanf("%d%d",&s[i].r,&s[i].l);
s[i].id = i ;
v[b[s[i].l]].push_back(s[i]);
}
for( int i = 1 ; i <= b[MAX] ; i++ ){
if( !v[i].size() ) continue;
sort( v[i].begin() , v[i].end() , cmp );
int ans = 0 , r = v[i][0].r , l = -1 ;
for( int j = 0 ; j < v[i].size() ; j++ ){
while( r < v[i][j].r ) ans = ( 0LL + ans + ans + MOD - C( r ++ , l ) ) % MOD;
while( r > v[i][j].r ) ans = ( ( ans + C( --r , l ) ) % MOD * inv[2] ) % MOD;
while( l < v[i][j].l ) ans = ( ans + C( r , ++l ) ) % MOD;
while( l > v[i][j].l ) ans = ( ans + MOD - C( r , l-- ) ) % MOD ;
res[v[i][j].id] = ans ;
}
}
for( int i = 1 ; i <= T ; i++ ) printf("%d\n",res[i]);
return 0 ;
}
两种分块方法,刚开始下面的一直wa,改了后也A了,放一下。
#include
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 3e5+66;
const int MOD = 1e9+7;
const int MAX = 1e5;
int b[AX];
int fac[AX];
int inv[AX];
int res[AX];
struct Node{
int l , r ;
int id ;
bool friend operator < ( const Node &x , const Node &y ){
return ( b[x.l] == b[y.l] ? x.r < y.r : b[x.l] < b[y.l] );
}
}s[AX];
int quick( int a , int b ){
int ans = 1 ;
while( b ){
if( b & 1 ){
ans = ( 1LL * ans * a ) % MOD;
}
b >>= 1 ;
a = ( 1LL * a * a ) % MOD;
}
return ans ;
}
int C(int a, int b){
return 1ll * fac[a] * inv[b] % MOD * inv[a - b] % MOD;
}
int main(){
int T;
fac[0] = 1;
for( int i = 1 ; i <= MAX ; i++ ){
fac[i] = 1LL * fac[i-1] * i % MOD ;
}
inv[MAX] = quick( fac[MAX] , MOD - 2 );
for( int i = MAX - 1 ; ~i ; i-- ){
inv[i] = 1LL * inv[i+1] * ( i + 1 ) % MOD;
}
scanf("%d",&T);
int len = sqrt(MAX);
for( int i = 1 ; i <= MAX ; i++ ){
b[i] = ( i - 1 ) / len + 1 ;
}
for( int i = 1 ; i <= T ; i ++ ){
scanf("%d%d",&s[i].r,&s[i].l);
s[i].id = i ;
}
LL ans = 1LL;
int l = 0 , r = 0 ;
sort( s + 1 , s + 1 + T );
for( int j = 1 ; j <= T ; j++ ){
while( r < s[j].r ) ans = ( 0LL + ans + ans + MOD - C( r ++ , l ) ) % MOD;
while( r > s[j].r ) ans = ( ( ans + C( --r , l ) ) % MOD * inv[2] ) % MOD;
while( l < s[j].l ) ans = ( ans + C( r , ++l ) ) % MOD;
while( l > s[j].l ) ans = ( ans + MOD - C( r , l-- ) ) % MOD ;
res[s[j].id] = ans ;
}
for( int i = 1 ; i <= T ; i++ ) printf("%d\n",res[i]);
return 0 ;
}