狠狠撸
Submit Search
情报科学シケスラ 贵颈产辞苍补肠肠颈
?
Download as PPTX, PDF
?
0 likes
?
1,433 views
tozan gezan
Follow
情报科学
Read less
Read more
1 of 23
Download now
Download to read offline
More Related Content
情报科学シケスラ 贵颈产辞苍补肠肠颈
1.
Information Science Fibonacci Sequence is
Magic 2014/01/28 tozangezan
2.
はじめに ? シケプリではありません(特に「プリ」が 違う) ? コラムが延々と続く感じです ?
Ruby書きたくないのでまともなソース コードは載せません ? 今回は漸化式で表される数列の計算をし ます。
3.
扱う漸化式 ? 以下の式を扱います ? このうちのkと求める項の番号nが与えら れるので、anを答える方法を考えます。 ?
k=2としたものがFibonacci数列です。 ? やり方はたくさんあります。 ? (以下、漸化式の係数をいじればすこし一般化できます)
4.
関数の再帰を使う F(n){ if n <
K then 1 else F(n-1)+F(n-2)+…+F(n-k) } (注)どの言語でもないので実行できません ? 再帰関数というのは 定義した関数の中に 同じ関数を呼び出す 機構があるものだと 思っておけばよいと 思います。 ? 漸化式をそのまま コードに書いたらこ んな感じになります。
5.
遅い! ? よく考えると、さっきのコードは少なく とも「1を返す回数」だけ関数が呼ばれて います ? これは答えの数と一致 ?
例えば、50番目のフィボナッチ数は 12586269025で、このプログラムだと数分 はかかりそう ? 計算量はだいたい O(αn) αは何かの定数 ? (Fibonacci数列なら黄金数とか)
6.
計算量:指数関数 ? 基本的に指数関数はダメです ? 参考 http://www.youtube.com/watch?v=Q4gTV4r0 zRs ?
「F(n)は何度も計算したところで毎回値同 じでは…」という発想だけで高速になりま す。
7.
関数のメモ化再帰をする F(n){ if “F(n)計算済み” then “計算済みの値” if
n < K then 1 else F(n-1)+F(n-2)+…+F(n-k) } (注)どの言語でもないので実行できません ? さっきのものに2行書 きたし、無駄に計算 しないようにしまし た。 ? かなり速く動くよう になります。 ? まだ漸化式から想像 がつくでしょう。
8.
メモ化再帰での計算量 ? 関数はnの値あたり1回しか呼び出されない としてよい ? (正確には何回か呼ばれてるだろうけど最初 の1文だけだしどうでもいい) ?
nの値によって関数は1回ずつ呼ばれて計 O(n) ? 関数1回ではK個の数の和を計算するので O(k) ? これら全部まとめるとO(nk)
9.
動的計画法を使う a[N] # 配列 ?
今度は関数を使わず に、ループをまわす a*1+=a*2+=…=a*k+=1 だけでかいてみまし for i in (k+1)..n た。 a[i]=a[i-1]+a[i-2++…+a*i-k] ? 本当はk個の数の和を 求めるのでもループ を使うんですがね。 ? コードが短め。
10.
動的計画法での計算量 ? メモ化再帰と同じ ? n回くらいループをまわしていて、
(O(n)) ? それぞれではk個の数の和を計算 (O(k)) ? 全部まとめると O(nk) ? やっぱりメモ化再帰と同じ
11.
問題 ? 以下の数列を考える ? このうちのkと求める項の番号nが与えら れるので、anを109+7で割ったあまりを答 えよ。 ?
k ≦ 100 ? n ≦ 100 000 ? 解答例: さっきのメモ化再帰,動的計画法
12.
問題 ? 以下の数列を考える ? このうちのkと求める項の番号nが与えら れるので、anを109+7で割ったあまりを答 えよ。 ?
k ≦ 100 ? n ≦ 1 000 000 000 000 000 000 ? 解答例: さっきのメモ化再帰,動的計画法
13.
別世界 ? ここから先はコード書くの面倒なのでか きません。 ? 情报科学の試験レベルなら別にこのくら いでゴールして良いんじゃないでしょう か。 ?
ここから先はkが大きいのには対処できま せんが、nが大きいのに対処できる方法で す。
14.
行列累乗 ? k=2のとき、 ? k=3のとき、 ?
办=4のとき、
15.
行列累乗 ? こういう感じの形になるので、anを得るた めには1を並べたベクトルにn-k回さっきの ような行列をかければよい。 ? 行列のかけ算 ?
A, A2, A4, A8, A16, A32, …は同じものをかける 処理をすると、全部でO(log n)回で求めら れる ? ほかのものが得たいときは、例えば A21= A × A4 × A16 などと2進数っぽくする。
16.
行列累乗での計算量 ? ということは、行列のかけ算はO(log n)回 行えばよい。 ?
ここで使う行列はk次正方行列なので1回 のかけ算はO(k3)かかる (定義に従って素直 に計算するしかない) ? ということで全体での計算量はO(k3 log n)
17.
問題 ? 以下の数列を考える ? このうちのkと求める項の番号nが与えら れるので、anを109+7で割ったあまりを答 えよ。 ?
k ≦ 100 ? n ≦ 1 000 000 000 000 000 000 ? 解答例: 行列累乗
18.
問題 ? 以下の数列を考える ? このうちのkと求める項の番号nが与えら れるので、anを109+7で割ったあまりを答 えよ。 ?
k ≦ 1 000 ? n ≦ 1 000 000 000 000 000 000 ? 解答例: 行列累乗
19.
整式の割り算を使う方法 ? 実は、この問題の第n項の値は、 「xnをxk-xk-1-xk-2-…-1で割ったあまりの係数 の総和」に等しいです。(証明略) xnをxk-xk-1-xk-2-…-1で割ったあまりは、x[n/2]を xk-xk-1-xk-2-…-1で割ったあまりを2乗し(nが奇 数ならさらにxをかける)、その式をxk-xk-1-xk2-…-1で割ったあまりを求めればよいです。
20.
整式の割り算を使う方法 ? k-1次の多項式二つの乗算はO(k2)でできま す ? この多項式の乗算はO(log
n)回呼ばれます ? ということで全体での計算量はO(k2 log n) です。
21.
参考問題 ? http://tdpc.contest.atcoder.jp/tasks/tdpc_fibo nacci ? けっこう多くの言語で(Rubyでも)解くこと ができるっぽいです。 ?
解答例 http://tdpc.contest.atcoder.jp/submissions/1193 05 (C++, 48行)
22.
おまけ ? 整式のかけ算は畳み込みなのでFFTで計算 できてO(k log
k)になります。 ? が、その整式を割ったあまりの計算がど うやったらO(k2)から落ちるかわかりませ ん。 ? 誰か教えてください ? あと、今回109+7で割ったあまりを求めた のは答えが大きくなりすぎるからです。
23.
The End
Download