zoukankan      html  css  js  c++  java
  • 数学基础 5

    数学基础 5

    前言

    因为 (3) 写不出来了 (4) 现在还空着 但是计划被打乱 所以来写 (5) (大雾


    目前还没写完 后面先咕着 学了之后再写


    拉格朗日插值

    拉格朗日插值法

    P4781 【模板】拉格朗日插值

    众所周知 给定 (n + 1) 个点 可以确定一个 (n) 次的多项式

    [f(x) = sum_{i = 0}^{n}y_iprod_{i e j}frac{x-x_j}{x_i - x_j} ]

    求其中某个点对应函数值时 将其代入即可

    证明? 没有证明(我并不会

    代码

    /*
      Time: 6.27
      Worker: Blank_space
      Source: P4781 【模板】拉格朗日插值
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #define int long long
    /*--------------------------------------头文件*/
    const int mod = 998244353;
    int n, k, X[2010], Y[2010], ans;
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int power(int _a, int _b, int res = 1) {for(; _b; _a = _a * _a % mod, _b >>= 1) if(_b & 1) res = res * _a % mod; return res;}
    /*----------------------------------------函数*/
    signed main() {
    	n = read(); k = read();
    	for(int i = 1; i <= n; i++) X[i] = read(), Y[i] = read();
    	for(int i = 1; i <= n; i++)
    	{
    		int tmp1 = Y[i], tmp2 = 1;
    		for(int j = 1; j <= n; j++) if(i != j)
    			tmp1 = (tmp1 * (k - X[j]) % mod + mod) % mod, tmp2 = (tmp2 * (X[i] - X[j]) % mod + mod) % mod;
    		ans = (ans + tmp1 * power(tmp2, mod - 2) % mod) % mod;
    	}
    	printf("%lld", ans);
    	return 0;
    }
    
    

    (x) 值连续的时候

    (x_i) 换成 (i) 有:

    [f(k) = sum_{i = 0}^ny_iprod_{i e j}frac{k - j}{i - j} ]

    考虑优化后面那一坨东西

    分子维护关于 (k) 的前缀积和后缀积 分母直接用阶乘来表示 式子为:

    [f(k) = sum_{i = 0}^nleft(-1 ight)^{n - i}y_ifrac{pre_{i - 1} imes suf_{i + 1}}{fac_i imes fac_{n - i}} ]


    重心拉格朗日插值法

    [egin{array}\ f(x) & = & sum_{i = 1}^ny_iprod_{i e j}frac{x - x_j}{x_i - x_j} \ & = & sum_{i = 1}^ny_ifrac{prod_{j e i}left(x - x_j ight)}{prod_{i e j}left(x_i - x_j ight)}\ & = & sum_{i = 1}^ny_ifrac{prod_{j = 1}^nleft(x - x_j ight)}{left(x - x_i ight)prod_{j e i}left(x_i - x_j ight) }\ & = & prod_{i = 1}^nleft(x - x_i ight)sum_{i = 1}^nfrac{y_i}{left(x - x_i ight)prod_{i e j}left(x_i - x_i ight)} end{array} ]

    (g = prod_{i = 1}^nleft(x - x_i ight), w(i) = prod_{j e i}left(x_i - x_j ight)) 有:

    [f(x) = gsum_{i = 1}^nfrac{y_i}{left(x - x_i ight)w(i)} ]

    对于每一个新增加的插值点 (O(n)) 的更新所有的 (w(i))

    代码

    /*
      Time: 6.27
      Worker: Blank_space
      Source:
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #define int long long
    /*--------------------------------------头文件*/
    const int mod = 1e9 + 7;
    int n, X[3010], Y[3010], W[3010], cnt;
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int power(int _a, int _b) {int res = 1; for(; _b; _a = _a * _a % mod, _b >>= 1) if(_b & 1) res = res * _a % mod; return res;}
    void insert(int x, int y) {
    	X[++cnt] = x; Y[cnt] = y; W[cnt] = 1;
    	for(int i = 1; i < cnt; i++) W[i] = W[i] * (X[i] - x) % mod, W[cnt] = W[cnt] * (x - X[i]) % mod;
    }
    void work(int x) {
    	int g = 1, ans = 0;
    	for(int i = 1; i <= cnt; i++)
    		if(X[i] == x) {printf("%lld
    ", Y[i]); return ;} 
    		else g = g * (x - X[i]) % mod;
    	for(int i = 1; i <= cnt; i++) 
    	ans = (ans + Y[i] * power((x - X[i]) * W[i], mod - 2) % mod + mod) % mod;
    	printf("%lld
    ", ans * g % mod);
    }
    /*----------------------------------------函数*/
    signed main() {
    	n = read();
    	for(int i = 1; i <= n; i++)
    	{
    		int opt = read(), x = read();
    		if(opt == 1) insert(x, read());
    		else work(x);
    	}
    	return 0;
    }
    
    

    自然数幂和

    定义

    (n) 个自然数 (k) 次幂的和为

    [S_k(n) = sum_{i = 1}^ni^k ]

    性质

    (S_k(n)) 为关于 (n)(k + 1) 次的多项式

    拉格朗日插值法

    需要 (k + 2) 个点来计算 可以直接取点 (O(k^2)) 的计算

    题目对于选择的点没有要求 当然可以选取连续的一段 按照上面那个直接带进去:

    [S_k(n) = sum_{i = 1}^{k + 2}(-1)^{k + 2 - i}S_k(i)frac{pre_{i - 1} imes suf_{i + 1}}{fac_{i} imes fac_{k + 2 - i}} ]

    复杂度: (O(klog k))

    代码:

    /*
      Time: 6.27
      Worker: Blank_space
      Source: CF622F The Sum of the k-th Powers
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #define int long long
    /*--------------------------------------头文件*/
    const int C = 1e6 + 7;
    const int mod = 1e9 + 7;
    /*------------------------------------常量定义*/
    int n, k, ans, tmp, pre[C], suf[C], fac[C];
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int power(int _a, int _b, int res = 1) {for(; _b; _a = _a * _a % mod, _b >>= 1) if(_b & 1) res = res * _a % mod; return res;}
    /*----------------------------------------函数*/
    signed main() {
    	n = read(); k = read(); pre[0] = suf[k + 3] = fac[0] = 1;
    	for(int i = 1; i <= k + 2; i++) pre[i] = pre[i - 1] * (n - i) % mod;
    	for(int i = k + 2; i >= 1; i--) suf[i] = suf[i + 1] * (n - i) % mod;
    	for(int i = 1; i <= k + 2; i++) fac[i] = fac[i - 1] * i % mod;
    	for(int i = 1; i <= k + 2; i++)
    	{
    		tmp = (tmp + power(i, k) % mod) % mod;
    		int x = pre[i - 1] * suf[i + 1] % mod;
    		int y = ((k - i & 1) ? -1 : 1) * fac[i - 1] * fac[k + 2 - i] % mod;
    		ans = (ans + tmp * x % mod * power(y, mod - 2) % mod + mod) % mod;
    	}
    	printf("%lld", ans);
    	return 0;
    }
    
    

    其他方法

    然而我并不会其他方法(巨雾

    题目

    教科书般的亵渎

    首先 由题:

    [ans = sum_{i = 0}^mleft(sum_{j = 1}^{n - a_i}j^{m + 1} - sum_{j = i + 1}^mleft(a_j - a_i ight)^{m + 1} ight) ]

    然而这个式子我并没有推出来

    然后? 然后就没有然后了 直接算就好了

    代码

    /*
      Time: 6.27
      Worker: Blank_space
      Source: P4593 [TJOI2018]教科书般的亵渎
    */
    /*--------------------------------------------*/
    #include<cstdio>
    #include<algorithm>
    #define int long long
    /*--------------------------------------头文件*/
    const int mod = 1e9 + 7;
    /*------------------------------------常量定义*/
    int T, n, m, k, a[60], ans, tmp, pre[60], suf[60], fac[60];
    /*------------------------------------变量定义*/
    inline int read() {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    /*----------------------------------------快读*/
    int power(int _a, int _b, int res = 1) {for(; _b; _a = _a * _a % mod, _b >>= 1) if(_b & 1) res = res * _a % mod; return res;}
    int Sum(int t) {
    	pre[0] = suf[k + 3] = fac[0] = 1; tmp = 0; int res = 0;
    	for(int i = 1; i <= k + 2; i++) pre[i] = pre[i - 1] * (t - i) % mod;
    	for(int i = k + 2; i >= 1; i--) suf[i] = suf[i + 1] * (t - i) % mod;
    	for(int i = 1; i <= k + 2; i++) fac[i] = fac[i - 1] * i % mod;
    	for(int i = 1; i <= k + 2; i++)
    	{
    		tmp = (tmp + power(i, k) % mod) % mod;
    		int x = pre[i - 1] * suf[i + 1] % mod;
    		int y = ((k - i & 1) ? -1 : 1) * fac[i - 1] * fac[k + 2 - i] % mod;
    		res = (res + tmp * x % mod * power(y, mod - 2) % mod + mod) % mod;
    	}
    	return res;
    }
    void work() {
    	n = read(); m = read(); ans = 0; k = m + 1;
    	for(int i = 1; i <= m; i++) a[i] = read();
    	std::sort(a + 1, a + 1 + m);
    	for(int i = 0; i <= m; i++)
    	{
    		int sum = Sum(n - a[i]) % mod;
    		for(int j = i + 1; j <= m; j++) sum = ((sum - power(a[j] - a[i], k) % mod) % mod + mod) % mod;
    		ans = (ans + sum) % mod;
    	}
    	printf("%lld
    ", (ans + mod) % mod);
    }
    /*----------------------------------------函数*/
    signed main() {
    	T = read(); while(T--) work();
    	return 0;
    }
    
    

    待填

  • 相关阅读:
    GeoServer与Spring MVC
    GeoServer二次开发1 hello Geoserver
    servlet的生命周期
    springboot打包出错,没有主清单
    空间数据库管理
    Gone with the wind
    谎言中的民众
    还是有些怀念这里啊
    MSN Protcol 学习笔记
    祝我的老师教师节快乐!
  • 原文地址:https://www.cnblogs.com/blank-space-/p/14941997.html
Copyright © 2011-2022 走看看