浅谈秦九韶算法

Posted 2020fengziyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈秦九韶算法相关的知识,希望对你有一定的参考价值。

浅谈秦九韶算法

好像FFT要用到,所以就学习一下
听说还是高中必修三的内容?

秦九韶算法的应用:

当我们知道 \\(x\\) 的值时,求下列式子的值:

\\[f(x) = a_0 + a_1x + a_2x^2 + a_3x^3 + \\cdots + a_n - 1x^n - 1 + a_nx^n \\]

一开始看到这个式子,我们肯定会想到直接带 \\(x\\) 进去乘不就行了吗
那秦九韶还提出来干什么
我们发现单单一个 \\(x^n\\) 就需要 \\(n - 1\\) 次乘法,那么一共就需要 \\(\\sum_i = 1 ^ n - 1i\\) 次乘法,和 \\(n\\) 次加法,如下 \\(n = 5\\) 时:

\\[f(x) = a_0 + a_1x + a_2x + a_3x + a_4x + a_5x \\]

就需要 \\(10\\) 次乘法和 \\(5\\) 次加法。
显然这个十分复杂,所以才要用到奏九韶算法
秦九韶算法就是将上述式子一步步化简成如下式子:

\\[f(x) = ( \\cdots (a_nx + a_n - 1)x + a_n - 2)x + \\cdots + a_1)x + a_0 \\]

我们发现这个虽然还是要用到 \\(n\\) 次加法,但是乘法次数下降到了 \\(n - 1\\) 次,所以这个只需要 \\(O(n)\\)的时间就可以实现了。

code

代码十分短

void qinjiushao()

    for(int i=n-1;i>=1;i--)
        ans*=x,ans+=a[i];

hdu6761 Mininum Index // lyndon分解 + duval贪心 + 秦九韶算法

link:http://acm.hdu.edu.cn/showproblem.php?pid=6761

建议学习该博客:https://blog.csdn.net/wayne_lee_lwc/article/details/107528945 

AC代码:(基本搬运...看了半天才懂了一点点...还要好好深入理解)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<iomanip>
#include<cstdio>
#include<string>

#define ll long long

using namespace std;

const int maxn = 2e7+10;
const int m = 1e9+7;

int n;
int pos[maxn];//记录以i为结尾的前缀串中,字典序最小的后缀的首字符的下标
char s[maxn];

void lyndon_duval()
{
    int i = 0,j,k;//i  j  k
    while(i < n){
        k = i;
        j = i + 1;
        //凡是与pos数组有关的下标皆需改动 
        while(j < n && s[j] >= s[k]){
            if(s[j] == s[k]){
                pos[j] = pos[k] + j - k;                
                k++;
            }else{
                k = i;
                pos[j] = i + 1;//此时为完整的lyndon串 
            }
            j++;
        }
        while(i <= k){
            i += j - k;
        }
        if(i == j && i < n){
            pos[j] = i + 1;//完全分解の特判 
        }
    }
}

void cal_out()
{
    ll ans = 0;
    for (int i = n - 1; i >= 0; i--) ans = (1112LL * ans + pos[i]) % m;//qjs 
    cout << ans << endl;
}

int main(){
    int T;cin >> T;
    
    while( T-- ){
        scanf("
");//略略略 
        cin >> s;
        n = strlen(s);//
        pos[0] = 1;
        lyndon_duval();        
        cal_out();    
    }
    //慎用memset!//本来想保险一点memset一波,结果超时...
    return 0;
}

 

以上是关于浅谈秦九韶算法的主要内容,如果未能解决你的问题,请参考以下文章

秦九韶算法详解

多项式计算之秦九韶算法

bzoj3157国王奇遇记(秦九韶算法+矩乘)

[计算机数值分析]利用秦九韶算法求多项式的值

多项式求值的秦九韶算法 python

hdu6761 Mininum Index // lyndon分解 + duval贪心 + 秦九韶算法