zoukankan      html  css  js  c++  java
  • Luogu P4781【模板】拉格朗日插值

    洛谷传送门

    板题…注意一下求多个数的乘积的逆元不要一个个快速幂求逆元,那样很慢,时间复杂度就是O(n2log)O(n^2log).直接先乘起来最后求一次逆元就行了.时间复杂度为O(nlog+n2)=O(n2)O(nlog+n^2)=O(n^2)

    这样的拉格朗日插值是预处理O(n2)O(n^2),插入O(n)O(n),查询O(n)O(n)的.使用的前提是可以求逆元.

    CODE

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    template<typename T>void read(T &num) {
    	char ch; int flg=1;
    	while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
    	for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
    	num*=flg;
    }
    const int MAXN = 2005;
    const int mod = 998244353;
    int n, k, x[MAXN], y[MAXN], w[MAXN];
    inline int qmul(int a, int b) {
    	int res = 1;
    	while(b) {
    		if(b&1) res = 1ll * res * a % mod;
    		a = 1ll * a * a % mod, b >>= 1;
    	}
    	return res;
    }
    inline int l(int k) {
    	int res = 1;
    	for(int i = 0; i < n; ++i)
    		res = 1ll * res * (k-x[i]) % mod;
    	return res;
    }
    int main() {
        read(n), read(k);
    	for(int i = 0; i < n; ++i)
    		read(x[i]), read(y[i]);
    	for(int i = 0; i < n; ++i) {
    		w[i] = 1;
    		for(int j = 0; j < n; ++j)
    			if(x[i]-x[j]) w[i] = 1ll * w[i] * (x[i]-x[j]) % mod; //这里先乘起来
    		w[i] = 1ll * qmul(w[i], mod-2) * y[i] % mod; //再求逆元
    	}
    	int Ans = 0;
    	for(int i = 0; i < n; ++i) {
    		if(k == x[i]) return printf("%d
    ", y[i]), 0; //虽然数据保证不会出现k=x[i]的情况,但还是判一下
    		Ans = (Ans + 1ll * w[i] * qmul(k-x[i], mod-2) % mod) % mod;
    	}
    	Ans = 1ll * Ans * l(k) % mod;
    	printf("%d
    ", (Ans + mod) % mod);
    }
    
    
  • 相关阅读:
    IAP
    golang笔记——map
    Unity自动打包 apk
    golang笔记——string
    golang笔记——数组与切片
    golang笔记——array
    golang笔记——struct
    golang笔记——流程控制
    golang笔记——数据类型
    golang笔记——IDE
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039396.html
Copyright © 2011-2022 走看看