目錄hany01。
meowww。
我們希望找到乙個演算法求出下面式子的值。
\[s_ = \sum_^i^k
\]一般來說要求時間複雜度不能與 n 有關。
乙個有用的結論 :\(s_\) 是乙個關於 n 的 k + 1 次多項式。
這是乙個中學老師(大概)要講的做法。
推導可以用擾動法,也可以用裂項相消法。
擾動法:記 \(s(n)=\sum_^a_k\),列等式 \(s(n)+a_=a_0+\sum_^a_k\)。此方法可解決等比數列求和等。我們採用裂項相消法。注意到 \((n+1)^ = \sum_^n^i = n^ + \sum_^n^i\)。
即 \((n + 1)^ - n^ = \sum_^n^i\)。求和可得:
\[\sum_^((i + 1)^ - i^) = \sum_^\sum_^i^j\\
(n + 1)^ =\sum_^s_
\]於是可以得到遞推式 \(s_ = \frac - \sum_^s_}\)。
該遞推式可以在給出 n 的情況下 \(o(k^2)\) 求出前 k 項,或者 \(o(k^3)\) 求出關於 n 的 k + 1 次多項式。
我們設指數型生成函式 \(f_n(x) = \sum_\fracx^i}\)。
作為一名熟練的 oi 選手,你可以將上面的遞推式看成生成函式卷積式,快速算出 \(f_n(x)\) 的表示式。
不過這裡直接根據定義推:
\[f_n(x) = \sum_\frac^j^i)x^i}\\
= \sum_^\sum_\frac
= \sum_^e^ = \frac - 1}
\]注意 \(e^x - 1\) 沒有逆元,不過 \(\frac\) 有。所以可以預處理出 \(b(x) = \frac\)(伯努利數的生成函式)。
所以 \(f_n(x) = \frac - x}b(x)\),直接卷積。注意是指數型生成函式所以還原時要乘階乘。
該方法可以在給出 n 的情況下 \(o(k\log k)\) 求出前 k 項,是求解自然數冪和的主要方法之一。
前面 \(s_\) 是乙個關於 n 的 k + 1 次多項式,因此可以插 k + 2 個點值求 \(s_\)。
先列出拉格朗日插值式:
\[s_ = \sum_^\frac^(x - j)}^(i - j)}s_
\]分子可以預處理 \((x - j)\) 的字首積與字尾積實現 \(o(k)\)。
分母是兩個階乘之積 + 可能存在的 (-1),預處理階乘的倒數實現 \(o(k)\)。
至於 \(s_\),考慮線性篩,只在素數處用 \(o(k\log k)\) 的快速冪,由素數的分布為 \(o(\frac)\) 得該演算法複雜度依然為 \(o(k)\)。
綜上,該方法可以在 \(o(k)\) 求出某一項 \(s_\),是求解自然數冪和的另一主要方法。
模板題:codeforces - 622f。
這些方法並不如上面兩種主流方法常用,但是具有一定啟發意義。
離散的數列求和 對應著 連續的函式積分。
連續的函式微分 對應回來,我們可以定義出 數列的差分運算:\(\delta f(x) = f(x + 1) - f(x)\)。
我們可以對數列進行多次差分,結果可以記作 \(\delta^k f(x) = \delta^f(x + 1) - \delta^f(x)\)
冪函式 \(f(x) = x^m\) 求導得 \(f'(x) = mx^\);而下降冪 \(f(x) = x^}\) 差分得 \(\delta f(x) = mx^}\)。
所以我們一般認為,連續的冪函式 \(x^m\) 對應為 離散的下降冪 \(x^}\)。
以上這些離散微積分的概念,雖然可以被其他概念取代,但可以讓你更了解數學之間的關聯性。
眾所周知可以通過斯特林數實現 冪 與 下降冪 之間的轉化:
\[n^m = \sum_^ n^}\\
n^} = \sum_^ (-1)^n^i
\]而 離散的下降冪求和 與 連續的冪積分 公式一樣,非常好算。
因此,我們借助斯特林數進行計算:
\[s_ = \sum_^i^k = \sum_^\sum_^ i^}\\
= \sum_^\sum_^i^} \\
= \sum_^\frac}}
\]只要預處理出斯特林數就可以 \(o(k)\) 算。
順便一提,用第一類斯特林數再把 \((n + 1)^}\) 展開,還可以得到 \(s_\) 關於 n + 1 的多項式。
一篇關於該方法的介紹:miskcoo。
模擬 連續函式的泰勒展開,離散數列也有個牛頓級數:
\[f(x) = \sum_\fracx^} = \sum_\delta^i f(0)
\]如果 f(x) 是乙個次數為 k 的多項式,經過 k + 1 次差分過後就會變為全 0 的數列了。因此多項式牛頓級數是 \(o(k)\) 項的。
可以用歸納法證明高維差分 \(\delta^n f(x) = \sum_^(-1)^f(x + i)\),這樣就與上面的部落格中所提到的結果是一致的。
如果把 \(s_ = \sum_^i^k\) 當成關於 n 的多項式,就可以用上面那篇部落格提到的方法 \(o(k)\) 做,不過和拉格朗日插值實在太像了。。。
關於這個方法有一道題(不是自然數冪和):bzoj - 4126。
連續自然數和
題目描述 對乙個給定的自然數m,求出所有的連續的自然數段,這些連續的自然數段中的全部數之和為m。例子 1998 1999 2000 2001 2002 10000,所以從1998到2002的乙個自然數段為m 10000的乙個解。輸入輸出格式 輸入格式 包含乙個整數的單獨一行給出m的值 10 m 2,...
連續自然數和
題目描述 描述 description 對乙個給定的自然數m,求出所有的連續的自然數段 連續個數大於1 這些連續的自然數段中的全部數之和為m。例子 1998 1999 2000 2001 2002 10000,所以從1998到2002的乙個自然數段為m 10000的乙個解。輸入輸入格式 input ...
從伯努利數到自然數冪和
伯努利數是定義在實數上的乙個數列,其在 rm oi 中的用處大多都是處理自然數冪和。我們定義伯努利數 b i 滿足 b 0 1,sum binomb i 0 n 0 那麼易得 b 0 1,b 1 frac,b 2 frac,b 3 0,b 4 frac,b 5 0,注意到奇數字除了 b 1 都為 0...