具體數學-第8課(取整進階)
原文鏈接:
具體數學-第8課 - WeiYang Blog
今天主要講了取整與遞歸式的結合,還有取模的相關知識。
例題1
給出下列遞歸式:
現在不要求你求解,要你證明:首先想到的就是數學歸納法,假設對於任意 ,都有 ,那麼:
如果 ,那麼 。如果 ,那麼 ,這時不成立。所以數學歸納法無法證明,今後我們會用其他方法來證明這個式子。
約瑟夫環新解
還記得約瑟夫環問題嗎?詳見第一節課。
這裡我們繼續推廣到一般情況,如果有 個人,每隔 個人踢掉一個人,最後剩下的是幾號?
初始編號為 ,現在考慮一種新的編號方式。
第一個人不會被踢掉,編號加 ,變成 ,然後第二個人編號變為 ,直到第 個人,他被踢掉了。
然後第 個人編號繼續加 ,變成了 ,依次下去。
考慮當前踢到的人編號為 ,那麼此時已經踢掉了 個人,所以接下去的人新的編號為 。
所以編號為 的人編號變成了 ,其中 。
直到最後,可以發現活下來的人編號為 ,問題是怎麼根據這個編號推出他原來的編號?
以 , 為例,下圖就是每個人新的編號:
令
所以他上一次的編號是 因為所以上一次編號可以寫為
因此最後存活的人編號可以用如下的演算法計算:
N = qnwhile N > n: N = k + N - nans = N
其中
如果我們用 替代 ,將會進一步簡化演算法:
演算法偽代碼如下:
D = 1while D <= (q-1)n: D = kans = qn + 1 - D
其中
模的性質
定義與性質
模定義如下:
特別的
與此類似,定義一個與模類似的運算:
形象理解如下圖所示:圓的周長是 ,一共走過的路長(紅色+綠色部分)是 ,所以 就是綠色部分, 就是一圈長度減去綠色部分。
模有一些性質:
應用
考慮如下問題,怎麼平均分配 個東西給 個人?
很容易想到,首先分給每個人 個東西,剩下 件東西分給前 個人,一人多一件就行。
概括起來就是,前 個人,每人 件,剩下的人,每人 件。
那有沒有辦法統一表示呢?有的,每個人分到的件數為
為什麼呢?假設
那麼 當 時,當 時,
得證,因此可以得到如下等式:
由
可以進一步將其轉換為下取整形式:令
我們得到了一個令人驚奇的等式:
HDU3089
最後用今天介紹的約瑟夫環演算法來解決一道經典的ACM題!題目鏈接:杭電3089。
C++代碼如下:
#include<bits/stdc++.h>using namespace std;typedef long long LL;LL Ceil(LL x, LL y) { if (x % y == 0) return x / y; return x / y + 1;}LL J(LL n, LL q) { LL D = 1, end = (q - 1) * n; while (D <= end) { D = Ceil(q * D, q - 1); } return q * n + 1 - D;}int main() { LL n, q; while (~scanf("%lld%lld", &n, &q)) { printf("%lld
", J(n, q)); } return 0;}
比網上各種快速演算法還要快哦,理論時間複雜度是 的。
推薦閱讀:
※Penn Geometry Festival
※那些數學140+的學霸,她們是怎麼做題的?
※水逆是指什麼?如何順利度過水逆期?
※拓撲學Ⅱ|筆記整理(1)——拓撲基本概念及性質,連續
※The Classification of covering space