<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hamko&#039;s Blog &#187; ProCon</title>
	<atom:link href="https://home.wakatabe.com/ryo/blog/?cat=14&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>https://home.wakatabe.com/ryo/blog</link>
	<description>This is an Intellect Hamster.</description>
	<lastBuildDate>Wed, 16 Apr 2014 07:45:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>C++0xのLambda式による量化関数</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=694</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=694#comments</comments>
		<pubDate>Sat, 04 Jan 2014 09:00:33 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=694</guid>
		<description><![CDATA[Lambda式の勉強をちょっとしたので、衝動的に量化関数を実装してみた。 どれくらい意味がわかりやすくなるかというと、こんな感じ。量化記号をそのまま実装できる点で、書きやすく意味が一目瞭然。 before after]]></description>
			<content:encoded><![CDATA[<p>Lambda式の勉強をちょっとしたので、衝動的に量化関数を実装してみた。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;
#define vi vector&lt;int&gt;
#define vit vector&lt;int&gt;::iterator
#define all(a) begin(a),end(a)

template &lt;class T, class LAMBDA&gt;
bool forall(T b, T e, LAMBDA l) {
    int faf = 1;
    for (T it = b; it != e; it++) {
        if (!l(it)) {
            faf = 0;
            break;
        }
    }
    return faf;
}
template &lt;class T, class LAMBDA&gt;
bool thereexists(T b, T e, LAMBDA l)
{
    return !forall(b, e, [l](T it) {return !l(it);});
}

main()
{
    vi a = {3, 6, 9, 12};

    // for all it in a there exists j in [4, 5], *it can divided by j -&gt; 0
    cout &lt;&lt;
        forall(all(a), [](vit it) {
            return thereexists(4, 5, [&amp;](int j) {
                return !(*it % j);
            });
        })
    &lt;&lt; endl;

    cout &lt;&lt; forall(2, 3, [&amp;](int it) {return it &gt; 2;}) &lt;&lt; endl; // 0
    cout &lt;&lt; forall(3, 4, [&amp;](int it) {return it &gt; 2;}) &lt;&lt; endl; // 1
    cout &lt;&lt; forall(all(a), [&amp;](decltype(begin(a)) it) {return !(*it % 2);}) &lt;&lt; endl; // 0
    cout &lt;&lt; forall(all(a), [&amp;](decltype(begin(a)) it) {return !(*it % 3);}) &lt;&lt; endl; // 1
    cout &lt;&lt; thereexists(all(a), [&amp;](decltype(begin(a)) it) {return !(*it % 5);}) &lt;&lt; endl; // 0
    cout &lt;&lt; thereexists(all(a), [&amp;](decltype(begin(a)) it) {return !(*it % 12);}) &lt;&lt; endl; // 1
}
</pre>
<p>どれくらい意味がわかりやすくなるかというと、こんな感じ。量化記号をそのまま実装できる点で、書きやすく意味が一目瞭然。<br />
<u>before</u></p>
<pre class="brush: cpp; title: ; notranslate">
        int flag = 0;
        for (auto itj = candidacy.begin(); itj != candidacy.end(); itj++) {
            if (iti == itj)
                continue;
            int faf = 1;
            for (int h = 0; h &lt; COLOR_NUM; h++) {
                if (!((*iti)[h] &gt;= (*itj)[h])) {
                    faf = 0;
                    break;
                }
            }
            if (!((*iti)[8] &gt;= (*itj)[8]))
                faf = 0;
            if (!faf) {
                continue;
            } else if (faf) {
                flag = 1;
                break;
            }
        }
        if (flag)
            iti = candidacy.erase(iti, iti + 1);
        else
            iti++;
</pre>
<p><u>after</u></p>
<pre class="brush: cpp; title: ; notranslate">
        if (there_exists(all(candidacy), [&amp;](itr(candidacy) itj) { return iti != itj &amp;&amp; (*iti)[8] &gt;= (*itj)[8] &amp;&amp; for_all(0, (int)COLOR_NUM, [&amp;](int h){ return (*iti)[h] &gt;= (*itj)[h]; });}))
            iti = candidacy.erase(iti, iti + 1);
        else
            iti++;
</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=694</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code Processor</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=546</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=546#comments</comments>
		<pubDate>Mon, 02 Dec 2013 04:00:08 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=546</guid>
		<description><![CDATA[http://gulfweed.starlancer.org/d/index.php?itemid=10 https://apps.topcoder.com/wiki/display/tc/How+to+install+The+Arena+plug-ins CodeProcessorはver 2.0ではいけない。]]></description>
			<content:encoded><![CDATA[<p>http://gulfweed.starlancer.org/d/index.php?itemid=10</p>
<p>https://apps.topcoder.com/wiki/display/tc/How+to+install+The+Arena+plug-ins</p>
<p>CodeProcessorはver 2.0ではいけない。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;stack&gt;
#include &lt;queue&gt;
#include &lt;climits&gt;
#include &lt;cmath&gt;
#include &lt;cstdio&gt;
#include &lt;cstdlib&gt;
#include &lt;cfloat&gt;
#include &lt;map&gt;
#include &lt;utility&gt;
#include &lt;set&gt;
#include &lt;iostream&gt;
#include &lt;memory&gt;
#include &lt;functional&gt;
#include &lt;sstream&gt;
#include &lt;complex&gt;
using namespace std;
static const double EPS = 1e-5;
#define EQ(a,b) (abs((a)-(b))&lt;EPS)

#define pb push_back
#define rep(i,n) for(int i = 0; i &lt; n; i++)
#define re return
#define all(x) (x).begin(), (x).end()
#define mp make_pair

typedef long long ll;
typedef long double ld;
typedef vector&lt;int&gt; vi;
typedef pair&lt;int, int&gt; ii;
typedef vector&lt;string&gt; vs;

template &lt;class T, class L&gt; bool for_all(T b, T e, L l) { int f = 1; for (T q = b; q != e; q++) { if (!l(q)) { f = 0; break; } } return f; }
template &lt;class T, class L&gt; bool there_exists(T b, T e, L l) { return !for_all(b, e, [l](T q) {return !l(q);}); }
class $CLASSNAME$ {

public:
    $RC$ $METHODNAME$($METHODPARMS$) {
        $RC$ result;
        return result;
    }

    $TESTCODE$
};

// BEGIN CUT HERE
int main() {
    $CLASSNAME$ ___test;
    ___test.run_test(-1);
}
// END CUT HERE
</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=546</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ビット演算まとめ</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=548</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=548#comments</comments>
		<pubDate>Fri, 22 Nov 2013 06:34:24 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=548</guid>
		<description><![CDATA[http://community.topcoder.com/tc?module=Static&#038;d1=tutorials&#038;d2=bitManipulation n &#038; (n-1) long long n; there exists m in N n = 2^mの判定。 __builtin_ctz(n) unsigned int n; count trailing zeros __builtin_ctz(n) = k * 2^m, k and 2 are coprimeなるm __builtin_ctz(n) = LSB(n) __builtin_clz(n) unsigned int n; count &#8230; <a href="https://home.wakatabe.com/ryo/blog/?p=548">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>http://community.topcoder.com/tc?module=Static&#038;d1=tutorials&#038;d2=bitManipulation</p>
<p>n &#038; (n-1)<br />
long long n;<br />
there exists m in N n = 2^mの判定。</p>
<p>__builtin_ctz(n)<br />
unsigned int n;<br />
count trailing zeros<br />
__builtin_ctz(n) = k * 2^m, k and 2 are coprimeなるm<br />
__builtin_ctz(n) = LSB(n)</p>
<p>__builtin_clz(n)<br />
unsigned int n;<br />
count leading zeros<br />
sizeof(n) &#8211; __builtin_clz(n) = argmin x < 2^i</p>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=548</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SRM 597</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=532</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=532#comments</comments>
		<pubDate>Thu, 21 Nov 2013 04:17:42 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=532</guid>
		<description><![CDATA[1184->1214(Blue) SRM 597 (div2), ox-, +50/-0, 264.1pts, 174th Div.1に戻りました。 Easy for all elem = a { amin = minelem(a), there exists m in N elem / amin = 2^m } を判定する。 どうでもいいけど、given nに対して、there exists m in N n=2^mの判定方法として、(n &#038; n &#8230; <a href="https://home.wakatabe.com/ryo/blog/?p=532">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>1184->1214(Blue)<br />
SRM 597 (div2), ox-, +50/-0, 264.1pts, 174th</p>
<p>Div.1に戻りました。<br />
<a href="http://apps.topcoder.com/wiki/display/tc/SRM+597" title="Problem"></a></p>
<p>Easy<br />
for all elem = a {<br />
  amin = minelem(a), there exists m in N elem / amin = 2^m<br />
}<br />
を判定する。<br />
どうでもいいけど、given nに対して、there exists m in N n=2^mの判定方法として、(n &#038; n &#8211; 1)がある。</p>
<p>Med<br />
result -1はソートして同一かチェック。<br />
result m ⇔ B[m:end]がAの部分列<br />
これだけで良いのだが、下の部分列として存在の実装をミスった。馬鹿です。部分問題に加えます。<br />
ミスった原因。<br />
-forやwhileがこんがらがる問題は、きちんと紙で構造を確かめなければならない。<br />
-終端条件から考えると楽<br />
-条件が網羅的であることを確認しなければならない<br />
-終端条件が更新条件によって変わる場合がある。下の解法2参照。<br />
-whileとbreak, continueの構造は極めてミスりやすいので、他の関数を作ったほうが良いと思われる。インクリメントの変数の取り扱いが面倒。</p>
<p>部分問題、string A, Bについて、AがBを部分列として持つかを判定せよ。<br />
解法0:<br />
B[i]がA[j:end]に存在するかを逐一チェック。<br />
終端条件<br />
i: last &#038;&#038; A[j:end]にB[i]がある→true<br />
i: last &#038;&#038; A[j:end]にB[i]がない→false<br />
i: not last &#038;&#038; A[j:end]にB[i]がない→false<br />
更新条件<br />
i: not last &#038;&#038; A[j:end]にB[i]がある→jをfind(A[j:end], B[i]) + 1に設定</p>
<p>解法1:<br />
B[i]がA[j:end]に存在するかを逐一チェック。<br />
終端条件<br />
j: done →false<br />
更新条件<br />
j: not done &#038;&#038; A[j] == B[i]→j++, break<br />
j: not done &#038;&#038; A[j] != B[i]→j++</p>
<p>解法2:<br />
whileとforの混成は面倒なので、while(1)でi, jを自分で管理する。<br />
終端条件<br />
i: not done &#038;&#038; j: done→false<br />
i: done &#038;&#038; j: not done→true<br />
i: done &#038;&#038; j: done→？？？<br />
更新条件<br />
i: not done &#038;&#038; j: not done &#038;&#038; A[j] == B[i]→i++, j++<br />
i: not done &#038;&#038; j: not done &#038;&#038; A[j] != B[i]→j++<br />
？？？は、更新条件1行目によって更新された時にのみ発生。これは？？？＝doneとして扱うべき。</p>
<pre class="brush: cpp; title: ; notranslate">
bool ans0(string A, string B)
{
    int j = 0;
    for (int i = 0; i &lt; B.length(); i++, j++) {
        int tmpj = A.substr(j, A.length() - j).find(B[i]);
        if (tmpj == string::npos) {
            return false;
        } else if (i != B.length() - 1) {
            j += tmpj;
        } else {
            return true;
        }
    }
    return true;
}


bool ans1(string A, string B)
{
    int j = 0;
    for (int i = 0; i &lt; B.length(); i++) {
        while (1) {
            if (A[j++] == B[i])
                break;
            if (j &gt;= A.length())
                return false;
        }
    }
    return true;
}

bool ans2(string A, string B)
{
    int i = 0, j = 0;
    while (1) {
        if (i &gt;= B.length())
            return true;
        else if (j &gt;= A.length())
            return false;
        else if (A[j] != B[i])
            j++;
        else {
            i++, j++;
        }
    }
}
</pre>
<p>Hard<br />
わけがわからないよ。<br />
勉強します。</p>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=532</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>プログラミングコンテスト部分問題集</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=430</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=430#comments</comments>
		<pubDate>Tue, 29 Oct 2013 08:59:41 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=430</guid>
		<description><![CDATA[コーディングの問題 string A, Bについて、AがBを部分列として持つかを判定するコードを書け。A, Bの長さは100以下． (SRM 597 Div.2 Med) DPの問題 bool配列Sについて、部分列S[a..b]に含まれる部分列の中で連続した1の最長の長さmaxlen(a, b)を考える。maxlenに関する漸化式を構成せよ。 (SRM 595 Div.1 Med) DPの問題 bool配列Sについて、以下を満たす部分列S[a..b]の場合の数を求めよ。条件: 最後にi回以上Trueが連続する、もしくはm回以上連続したTrueが存在する。 (SRM 595 Div.1 Med)]]></description>
			<content:encoded><![CDATA[<p>コーディングの問題<br />
string A, Bについて、AがBを部分列として持つかを判定するコードを書け。A, Bの長さは100以下． (SRM 597 Div.2 Med)</p>
<p>DPの問題<br />
bool配列Sについて、部分列S[a..b]に含まれる部分列の中で連続した1の最長の長さmaxlen(a, b)を考える。maxlenに関する漸化式を構成せよ。 (SRM 595 Div.1 Med)</p>
<p>DPの問題<br />
bool配列Sについて、以下を満たす部分列S[a..b]の場合の数を求めよ。条件: 最後にi回以上Trueが連続する、もしくはm回以上連続したTrueが存在する。 (SRM 595 Div.1 Med)</p>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=430</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SRM 595</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=421</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=421#comments</comments>
		<pubDate>Tue, 29 Oct 2013 04:54:09 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=421</guid>
		<description><![CDATA[Analysis http://topcoder.g.hatena.ne.jp/evima/20131025 Div.2に落ちました。大いに反省します。 Easy LittleElephantAndIntervalsDiv1 Div.1 Easyにしてはかなり簡単だったはず。塗りつぶす時に何故か逆の順番で塗って死亡。 答え: 2^最終結果に残っている操作の種類数 以下、コーディングの勉強。 2^numの仕方。 種類の数え方。 Medium 手も足も出なかった感じ。まぁDiv.1 Medはいつもこんな感じ。 問題自体について 「S[a..b] + S[ c..d] にGがm回連続で現れる」とは、次のうちどれか1つ以上が成り立つこと 条件A: S[a..b]にGがm回連続で現れる 条件B: S[ c..d]にGがm回連続で現れる 条件C: S[a..b]の終わりの部分と、S[ c..d]の始めの部分をつなげるとGがm回連続で現れる」 「#(AorBorC) = #(A)+#(B)+#(C)-#(AandB)-#(BandC)-#(CandA)+#(AandBandC)」 ということを整理した上で、a, bを固定して、c, dの場合の数をO(1)で求める方法を考える。 戦略的な問題 ・問題は部分分解すべき。条件AorBを満たす場合の数、などはべん図が利用可能。 ・AorBに応じてCをする、みたいな計算は、本当は4つ実装しなければならないが、効果が一致するならば場合分けをまとめてよい。しかし、思考過程では場合分けしていなければならない。 ・欲しいもの駆動でトップダウンに考えるべき。 ・欲しいものがあったら全て置いてしまう。そこで初めて漸化式が書けるようになる。 &#8230; <a href="https://home.wakatabe.com/ryo/blog/?p=421">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href=http://apps.topcoder.com/wiki/display/tc/SRM+595>Analysis</a></p>
<p>http://topcoder.g.hatena.ne.jp/evima/20131025</p>
<p>Div.2に落ちました。大いに反省します。</p>
<p>Easy <a href="http://community.topcoder.com/stat?c=problem_statement&#038;pm=12822&#038;rd=15707">LittleElephantAndIntervalsDiv1</a><br />
Div.1 Easyにしてはかなり簡単だったはず。塗りつぶす時に何故か逆の順番で塗って死亡。<br />
答え: 2^最終結果に残っている操作の種類数<br />
以下、コーディングの勉強。<br />
2^numの仕方。</p>
<pre class="brush: cpp; title: ; notranslate">
1LL &lt;&lt; num // (long long)2^num;
</pre>
<p>種類の数え方。</p>
<pre class="brush: cpp; title: ; notranslate">
set&lt;int&gt; s;
set.insert(1):
set.insert(1):
set.insert(2):
set.insert(2):

cout &lt;&lt; set.size() &lt;&lt; endl;
</pre>
<p>Medium <a href="http://community.topcoder.com/stat?c=problem_statement&#038;pm=12113&#038;rd=15707" title="LittleElephantAndRGB"></a><br />
手も足も出なかった感じ。まぁDiv.1 Medはいつもこんな感じ。<br />
問題自体について<br />
「S[a..b] + S[ c..d] にGがm回連続で現れる」とは、次のうちどれか1つ以上が成り立つこと<br />
条件A: S[a..b]にGがm回連続で現れる<br />
条件B: S[ c..d]にGがm回連続で現れる<br />
条件C: S[a..b]の終わりの部分と、S[ c..d]の始めの部分をつなげるとGがm回連続で現れる」<br />
「#(AorBorC) = #(A)+#(B)+#(C)-#(AandB)-#(BandC)-#(CandA)+#(AandBandC)」<br />
ということを整理した上で、a, bを固定して、c, dの場合の数をO(1)で求める方法を考える。</p>
<p>戦略的な問題<br />
・問題は部分分解すべき。条件AorBを満たす場合の数、などはべん図が利用可能。<br />
・AorBに応じてCをする、みたいな計算は、本当は4つ実装しなければならないが、効果が一致するならば場合分けをまとめてよい。しかし、思考過程では場合分けしていなければならない。<br />
・欲しいもの駆動でトップダウンに考えるべき。<br />
・欲しいものがあったら全て置いてしまう。そこで初めて漸化式が書けるようになる。<br />
・漸化式を書くために描く模式図は、既知前提部分をボックスにするとよい。ボックスの性質がかける程度に大きめに。</p>
<p>アルゴリズムの問題<br />
いわゆる「前処理を頑張る」という奴。<br />
O(N^2)の処理の中でO(N^2)の処理をするとO(N^4)になるが<br />
二回目のO(N^2)をO(1)で参照可能なテーブルを作るための、O(N^2)が存在すれば、全体もO(N^2)となる。</p>
<p>漸化式で扱われているものは、そのループは漸化的な方向に回す。</p>
<p>逐次的なDPについて。<br />
DPは必ずしも全部メモリに取っておかなければならない訳ではなく、むしろ計算に最小限のバッファとしてメモリを利用することが望まれる。<br />
一方で、本当はO(1)でいいDPを後の計算の事情でO(M)にしたりすることができる。<br />
漸化的な変数と漸化的でない変数が含まれるとき、これのループの順番をうまくコーディングすれば、<br />
・外で回している方のメモリサイズNに対してM(N)を利用できる。<br />
・外側のループのスコープで、DPの計算結果をO(1)で利用できる。その後の計算に何が必要なのかとの兼ね合い。</p>
<p>これは、以下のような考え方から導かれる。<br />
図で考える。-|が回ったループ、cが計算された値、*が未計算の値だとする。<br />
漸化的変数を先に持ってくると、<br />
c****<br />
c****<br />
c****<br />
↓<br />
cc***<br />
cc***<br />
cc***<br />
↓<br />
ccccc<br />
ccccc<br />
ccccc</p>
<p>逆に、漸化的でない変数を後に持ってくると、<br />
c****<br />
c****<br />
c****<br />
↓<br />
ccccc<br />
c****<br />
c****<br />
↓<br />
ccccc<br />
ccccc<br />
ccccc</p>
<p>以下はforの順番を逆にしても計算量に影響を出さずに、メモリオーダを調整可能であることを例示するコード。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;iostream&gt;
#include &lt;vector&gt;

#define NUM 5
using namespace std;

void print_vec(vector&lt;int&gt;&amp; v)
{
    for (int i = 0; i &lt; v.size(); i++) 
            cout &lt;&lt; v[i] &lt;&lt; &quot; &quot;;
    cout &lt;&lt; endl;
}

int f(int a)
{
    return a * 2 + 1;
}

void dp_ji(void) 
{
    cout &lt;&lt; &quot;#ji&quot; &lt;&lt; endl;
    vector&lt;int&gt; tj = {1, 2, 3, 4};
    print_vec(tj);
    for (int j = 0; j &lt; NUM-1; j++) {
        for (int i = 0; i &lt; tj.size(); i++) 
            tj[i] = f(tj[i]);
        print_vec(tj);
    }
}

void dp_ij(void) 
{
    cout &lt;&lt; &quot;#ij&quot; &lt;&lt; endl;
    vector&lt;int&gt; tj = {1, 2, 3, 4};
    vector&lt;int&gt; ti(NUM);
    for (int i = 0; i &lt; tj.size(); i++) {
        ti[0] = tj[i];
        for (int j = 0; j &lt; NUM; j++) 
            ti[j+1] = f(ti[j]);
        print_vec(ti);
    }
}

int main(void)
{
    dp_ji();
    dp_ij();
    return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=421</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOJ 0042: A Thief</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=74</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=74#comments</comments>
		<pubDate>Thu, 27 Jun 2013 19:05:27 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=74</guid>
		<description><![CDATA[A Thief コード ただのナップサック問題。だったので、紙を使わずに暗算で漸化式を立てて解きました。 dp[j][i] = i個目までの美術品をjの重さで盗んだ時の価値の最大値 初期状態は、dp[j][0] = 0 for all j 漸化式は、dp[j][i] = max(dp[j][i], dp[j-w][i]))で更新。]]></description>
			<content:encoded><![CDATA[<p><a href="http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0042">A Thief</a><br />
<a href="http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=703165">コード</a></p>
<p>ただのナップサック問題。だったので、紙を使わずに暗算で漸化式を立てて解きました。</p>
<p>dp[j][i] = i個目までの美術品をjの重さで盗んだ時の価値の最大値<br />
初期状態は、dp[j][0] = 0 for all j<br />
漸化式は、dp[j][i] = max(dp[j][i], dp[j-w][i]))で更新。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;stdio.h&gt;
 
using namespace std;
 
#define WMAX 1000
#define NMAX 1000
int main(void)
{
    int W, n;
    int cyc = 0;
    while (cin &gt;&gt; W &amp;&amp; W &amp;&amp; cin &gt;&gt; n) {
        cyc++;
        int dp[WMAX+1][NMAX+1] = {};
        for (int i = 0; i &lt; n; i++) {
            int v, w;
            scanf(&quot;%d,%d&quot;, &amp;v, &amp;w);
            for (int j = 0; j &lt; W+1; j++) 
                dp[j][i+1] = max(dp[j][i], (j-w &gt;= 0 ? dp[j-w][i] + v : 0));
        }
        cout &lt;&lt; &quot;Case &quot; &lt;&lt; cyc &lt;&lt; &quot;:&quot; &lt;&lt; endl;
        for (int j = 0; j &lt; W+1; j++) {
            if (dp[j][n] == dp[W][n]) {
                cout &lt;&lt; dp[j][n] &lt;&lt; endl &lt;&lt; j &lt;&lt; endl;
                break;
            }
        }
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=74</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOJ 2301: Sleeping Time</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=68</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=68#comments</comments>
		<pubDate>Wed, 26 Jun 2013 23:59:20 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=68</guid>
		<description><![CDATA[Sleeping Time コード 難易度Blue 350 (非公式難易度表) 「k回の睡眠でR=r, L=lとした時のPP」を返す関数retを考えて、深さ優先探索を行う発想は自然。 だが、これだけでは2^30で計算が間に合わない。 なので、l, rとP, Eの関係に枝刈り条件を加える。 ret内のl-rを呼び出し回数に関して指数関数的に収束させていくので、この条件はかなり強い枝刈りが可能である。]]></description>
			<content:encoded><![CDATA[<p><a href="http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2301">Sleeping Time</a><br />
<a href="http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=698061">コード</a></p>
<p>難易度<font color="blue">Blue 350</font> (<a href="https://docs.google.com/spreadsheet/ccc?key=0Ank515IguQc4dGJDR3FYOGZGTXQ5VHhNa1JmMDB4U0E#gid=0">非公式難易度表</a>)</p>
<p>「k回の睡眠でR=r, L=lとした時のPP」を返す関数retを考えて、深さ優先探索を行う発想は自然。<br />
だが、これだけでは2^30で計算が間に合わない。</p>
<p>なので、l, rとP, Eの関係に枝刈り条件を加える。<br />
ret内のl-rを呼び出し回数に関して指数関数的に収束させていくので、この条件はかなり強い枝刈りが可能である。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;iostream&gt;
#include &lt;cstdio&gt;
using namespace std;
#define abs(a) ((a) &gt; 0 ? (a) : -(a))
 
double P, E, T;
double ret(double k, double r, double l)
{
    double h = (r + l) / 2;
    if (k == 0) 
        return (abs(h-T) &lt; E ? 1.0 : 0.0);
    if (l &lt; T - E)
        return 0.0;
    if (r &gt; T + E) 
        return 0.0;
    if (T - E &lt; r &amp;&amp; l &lt; T + E) 
        return 1.0;
    if ((r+l)/2 &gt;= T) 
        return P * ret(k-1, r, h) + (1.0 - P) * ret(k-1, h, l);
    else
        return P * ret(k-1, h, l) + (1.0 - P) * ret(k-1, r, h);
}
 
int main(void)
{
    double K, R, L;
    cin &gt;&gt; K &gt;&gt; R &gt;&gt; L &gt;&gt; P &gt;&gt; E &gt;&gt; T;
    P = 1 - P;
 
    printf(&quot;%.6f&quot;, ret(K, R, L));
    return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=68</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOJ 2015: Square Route</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=61</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=61#comments</comments>
		<pubDate>Wed, 26 Jun 2013 11:25:56 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=61</guid>
		<description><![CDATA[Square Route コード 縦横で生成しうる辺の長さをそれぞれ全て求める。 それをソートしてしゃくとり法によって同じ長さの辺をかけて足し算していく。 でも、mapを使ってベクトルの内積をすればいいだけでは…と後で気づいた。]]></description>
			<content:encoded><![CDATA[<p><a href="http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2015">Square Route</a><br />
<a href="http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=693328">コード</a></p>
<p>縦横で生成しうる辺の長さをそれぞれ全て求める。<br />
それをソートしてしゃくとり法によって同じ長さの辺をかけて足し算していく。<br />
でも、mapを使ってベクトルの内積をすればいいだけでは…と後で気づいた。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;vector&amp;gt;

using namespace std;
#define NUMMAX 1500
#define CMAX (NUMMAX * (NUMMAX + 1) / 2)

void makecvec(vector&amp;lt;int&amp;gt;&amp;amp; in, vector&amp;lt;int&amp;gt;&amp;amp; out) 
{
    for (int ni = 0; ni &amp;lt; (int)in.size(); ni++) {
        for (int pi = 0; pi &amp;lt; (int)in.size() - ni; pi++) {
            int sum = 0;
            for (int si = 0; si &amp;lt; ni + 1; si++)
                sum += in[pi + si];
            out.push_back(sum);
        }
    }
}

int main(void)
{
    int n, m;
    while (cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m) {
        if (!n &amp;amp;&amp;amp; !m) break;
        vector&amp;lt;int&amp;gt; h(n), w(m);
        for (int i = 0; i &amp;lt; n; i++) cin &amp;gt;&amp;gt; h[i];
        for (int i = 0; i &amp;lt; m; i++) cin &amp;gt;&amp;gt; w[i];

        vector&amp;lt;int&amp;gt; hs, ws;
        hs.reserve(CMAX), ws.reserve(CMAX);
        makecvec(h, hs), makecvec(w, ws);
        sort(hs.begin(), hs.end()), sort(ws.begin(), ws.end());

        int result = 0;
        int hi = 0, wi = 0;
        while (hi != (int)hs.size() &amp;amp;&amp;amp; wi != (int)ws.size()) {
            if (hs[hi] == ws[wi]) {
                int hn = 0, wn = 0;
                while (hi != (int)hs.size() &amp;amp;&amp;amp; hs[hi] == hs[hi-hn]) 
                    hi++, hn++;
                while (wi != (int)ws.size() &amp;amp;&amp;amp; ws[wi] == ws[wi-wn]) 
                    wi++, wn++;
                result += wn * hn;
            } else if (hs[hi] &amp;lt; ws[wi]) 
                hi++;
            else 
                wi++;
        }
        cout &amp;lt;&amp;lt; result &amp;lt;&amp;lt; endl;
    }

    return 0;
}

</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=61</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AOJ 0557: 1年生 (A First Grader)</title>
		<link>https://home.wakatabe.com/ryo/blog/?p=54</link>
		<comments>https://home.wakatabe.com/ryo/blog/?p=54#comments</comments>
		<pubDate>Wed, 26 Jun 2013 11:17:27 +0000</pubDate>
		<dc:creator>Hamko</dc:creator>
				<category><![CDATA[ProCon]]></category>

		<guid isPermaLink="false">http://home.wakatabe.com/ryo/blog/?p=54</guid>
		<description><![CDATA[1年生 (A First Grader) コード DP強化週間 num[j] = j項目の数字 a[i][j] = j個目までの数字を使ってAOJ君が計算可能な数式によって、iを作る時の場合の数 とすると、以下のような漸化式が立てられる。 a[j][i] = a[j + num[i]][i-1] (もしj + num[i] < 21なら) + a[j - num[i]][i-1] (もしj - num[i] >= 0) i番目までで作れる0から20の数字を記憶する。何を展開して漸化式を立てるか、という問題は、もともと少ない自由度をわざわざ大きくする、という点で発想的だよなー。]]></description>
			<content:encoded><![CDATA[<p><a href="http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0557">1年生 (A First Grader)</a><br />
<a href="http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=698471">コード</a></p>
<p><a href="http://d.hatena.ne.jp/kyuridenamida/20111009/1318091499">DP強化週間</a></p>
<p> num[j] = j項目の数字<br />
 a[i][j] = j個目までの数字を使ってAOJ君が計算可能な数式によって、iを作る時の場合の数</p>
<p>とすると、以下のような漸化式が立てられる。</p>
<p> a[j][i] = a[j + num[i]][i-1] (もしj + num[i] < 21なら) + a[j - num[i]][i-1] (もしj - num[i] >= 0)</p>
<p>i番目までで作れる0から20の数字を記憶する。何を展開して漸化式を立てるか、という問題は、もともと少ない自由度をわざわざ大きくする、という点で発想的だよなー。</p>
<pre class="brush: cpp; title: ; notranslate">
#include &lt;iostream&gt;
#include &lt;vector&gt;

using namespace std;

int main(void)
{
    int n;
    cin &gt;&gt; n;
    int num[101];
    for (int i = 0; i &lt; n-1; i++) 
        cin &gt;&gt; num[i];
    int dest;
    cin &gt;&gt; dest;

    long long a[21][101] = {};
    a[num[0]][0] = 1;
    for (int i = 1; i &lt; n-1; i++) 
        for (int j = 0; j &lt; 21; j++) 
            a[j][i] += ((j + num[i] &lt; 21) ? a[j + num[i]][i-1] : 0) + ((j - num[i] &gt;= 0) ? a[j - num[i]][i-1] : 0);
    cout &lt;&lt; a[dest][n-1-1] &lt;&lt; endl;

    return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://home.wakatabe.com/ryo/blog/?feed=rss2&#038;p=54</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
