【HDU】5275 pog loves szh IV【拉格朗日插值法】
2015-06-29 19:40
288 查看
传送门:【HDU】5275 pog loves szh IV
题目分析:首先,队友给了我一个拉格朗日插值法的公式,裸的OWO,如下:
∑i=lr{yi∏i!=j(xi−xj)∏i!=j(x−xj)}\sum_{i=l}^{r}\{\frac{y_i}{\prod_{i!=j}(x_i-x_j)}\prod_{i!=j}(x-x_j)\}
只要把题目给的坐标带入xi,xj,yi,xx_i,x_j,y_i,x,就可以求出答案了……
然后我们要怎么求呢?首先要求xi−xjx_i-x_j的逆元,因为最多只有500000种,且分布在[-250000,250000],且关于y轴−x-x的逆元和xx的逆元互为相反数,于是我们只用求[1,250000]内的逆元即可。
然后对于∏i!=j(xi−xj)\prod_{i!=j}(x_i-x_j),我们可以O(N2)O(N^2)预处理。然后每次查询,∏i!=j(x−xj)\prod_{i!=j}(x-x_j)是可以预先算的,因为∏i!=j(x−xj)=∏(x−xj)x−xi\prod_{i!=j}(x-x_j)=\frac{\prod(x-x_j)}{x-x_i},这里我们需要注意的一点是,x−xix-x_i可能为0,此时没有逆元,这时候因为xix_i各不相同,于是x−xix-x_i等于0的项最多出现一次,这时候我们暴力算就行了。
于是总复杂度为O(N2+NQ)O(N^2+NQ)
my code:my~~code:
题目分析:首先,队友给了我一个拉格朗日插值法的公式,裸的OWO,如下:
∑i=lr{yi∏i!=j(xi−xj)∏i!=j(x−xj)}\sum_{i=l}^{r}\{\frac{y_i}{\prod_{i!=j}(x_i-x_j)}\prod_{i!=j}(x-x_j)\}
只要把题目给的坐标带入xi,xj,yi,xx_i,x_j,y_i,x,就可以求出答案了……
然后我们要怎么求呢?首先要求xi−xjx_i-x_j的逆元,因为最多只有500000种,且分布在[-250000,250000],且关于y轴−x-x的逆元和xx的逆元互为相反数,于是我们只用求[1,250000]内的逆元即可。
然后对于∏i!=j(xi−xj)\prod_{i!=j}(x_i-x_j),我们可以O(N2)O(N^2)预处理。然后每次查询,∏i!=j(x−xj)\prod_{i!=j}(x-x_j)是可以预先算的,因为∏i!=j(x−xj)=∏(x−xj)x−xi\prod_{i!=j}(x-x_j)=\frac{\prod(x-x_j)}{x-x_i},这里我们需要注意的一点是,x−xix-x_i可能为0,此时没有逆元,这时候因为xix_i各不相同,于是x−xix-x_i等于0的项最多出现一次,这时候我们暴力算就行了。
于是总复杂度为O(N2+NQ)O(N^2+NQ)
my code:my~~code:
[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 ; }
相关文章推荐
- Vi经典插件
- 全排列——火车进站问题(华为OJ)
- 方向导数和梯度
- 网站变为黑白
- 【机房收费系统】经过时间and换行符
- Linux内存管理--逻辑层面分析
- android4.4 魔趣 使用go备份的解决方案。
- 2015百度校招用户行为分析研发工程师笔试题
- BZOJ3748 : [POI2015]Kwadraty
- 用python作个简单文件拷贝操作
- 基于JavaCV的人脸识别软件
- linux 使用expect
- 如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧
- Python重定向到文件
- idea14 maven项目 jdk编译版本无法修改
- CocoaPods安装问题
- Mac下安装并使用Boost(解决方案)
- 如何修改android系统字体大小
- IOS--OC--LessonDictionary 字典
- 如何撰写科研课题结题报告