传送门:【HDU】5275 Dylans loves polynomial
题目分析:首先,队友给了我一个拉格朗日插值法的公式,裸的OWO,如下:
∑
i
=
l
r
{
y
i
∏
i
!
=
j
(
x
i
−
x
j
)
∏
i
!
=
j
(
x
−
x
j
)
}
\sum_{i=l}^{r}\{\frac{y_i}{\prod_{i!=j}(x_i-x_j)}\prod_{i!=j}(x-x_j)\}
i=l∑r{∏i!=j(xi−xj)yii!=j∏(x−xj)}
只要把题目给的坐标带入
x
i
,
x
j
,
y
i
,
x
x_i,x_j,y_i,x
xi,xj,yi,x,就可以求出答案了……
然后我们要怎么求呢?首先要求
x
i
−
x
j
x_i-x_j
xi−xj的逆元,因为最多只有500000种,且分布在[-250000,250000],且关于y轴
−
x
-x
−x的逆元和
x
x
x的逆元互为相反数,于是我们只用求[1,250000]内的逆元即可。
然后对于
∏
i
!
=
j
(
x
i
−
x
j
)
\prod_{i!=j}(x_i-x_j)
∏i!=j(xi−xj),我们可以
O
(
N
2
)
O(N^2)
O(N2)预处理。然后每次查询,
∏
i
!
=
j
(
x
−
x
j
)
\prod_{i!=j}(x-x_j)
∏i!=j(x−xj)是可以预先算的,因为
∏
i
!
=
j
(
x
−
x
j
)
=
∏
(
x
−
x
j
)
x
−
x
i
\prod_{i!=j}(x-x_j)=\frac{\prod(x-x_j)}{x-x_i}
∏i!=j(x−xj)=x−xi∏(x−xj),这里我们需要注意的一点是,
x
−
x
i
x-x_i
x−xi可能为0,此时没有逆元,这时候因为
x
i
x_i
xi各不相同,于是
x
−
x
i
x-x_i
x−xi等于0的项最多出现一次,这时候我们暴力算就行了。
于是总复杂度为 O ( N 2 + N Q ) O(N^2+NQ) O(N2+NQ)
m y c o d e : my~~code: my code:
#include <bits/stdc++.h>
using namespace std ;
typedef long long LL ;
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
const int MAXN = 3005 ;
const int MAXM = 250005 ;
const int mod = 1e9 + 7 ;
int mul[MAXN][MAXN] ;
int inv[MAXM] ;
int p[MAXN][2] ;
int n , q ;
int power ( int a , int b ) {
LL res = 1 , tmp = a ;
for ( ; b ; b >>= 1 , tmp = tmp * tmp % mod ) {
if ( b & 1 ) res = res * tmp % mod ;
}
return res ;
}
void preprocess () {
for ( int i = 1 ; i <= n ; ++ i ) {
mul[i][i] = 1 ;
for ( int j = i + 1 ; j <= n ; ++ j ) {
mul[i][j] = ( LL ) mul[i][j - 1] * inv[abs ( p[i][0] - p[j][0] )] % mod * ( p[i][0] < p[j][0] ? -1 : 1 ) ;
if ( mul[i][j] < 0 ) mul[i][j] += mod ;
}
for ( int j = i - 1 ; j >= 1 ; -- j ) {
mul[i][j] = ( LL ) mul[i][j + 1] * inv[abs ( p[i][0] - p[j][0] )] % mod * ( p[i][0] < p[j][0] ? -1 : 1 ) ;
if ( mul[i][j] < 0 ) mul[i][j] += mod ;
}
}
}
void solve () {
int l , r , x ;
for ( int i = 1 ; i <= n ; ++ i ) {
scanf ( "%d%d" , &p[i][0] , &p[i][1] ) ;
}
preprocess () ;
scanf ( "%d" , &q ) ;
for ( int i = 1 ; i <= q ; ++ i ) {
scanf ( "%d%d%d" , &l , &r , &x ) ;
int res = 0 , tot = 1 ;
for ( int j = l ; j <= r ; ++ j ) {
tot = ( LL ) tot * ( x - p[j][0] ) % mod ;
}
for ( int j = l ; j <= r ; ++ j ) {
int tmp = ( LL ) p[j][1] * mul[j][l] % mod * mul[j][r] % mod ;
if ( x != p[j][0] ) tmp = ( LL ) tmp * tot % mod * inv[abs ( x - p[j][0] )] % mod * ( x < p[j][0] ? -1 : 1 ) ;
else {
int t = 1 ;
for ( int k = l ; k <= r ; ++ k ) {
if ( k != j ) t = ( LL ) t * ( x - p[k][0] ) % mod ;
}
tmp = ( LL ) tmp * t % mod ;
}
if ( tmp < 0 ) tmp += mod ;
res = ( res + tmp ) % mod ;
}
printf ( "%d\n" , res ) ;
}
}
int main () {
inv[0] = 1 ;
for ( int i = 1 ; i < MAXM ; ++ i ) {
inv[i] = power ( i , mod - 2 ) ;
}
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}