ICPC2018国内予選参加記 Tech-ONC

こんばんえるえる〜〜
毎度ガナリヤです!
部室行かなくてすいません!活動はしてるんです!集中力の問題で家でやってます・・・(お兄さん許して・・・)
今日は、ICPC国内予選に参加したので、来年のリベンジのために参加記を残しておこうとおもいます。
 
 

チーム Tech-ONC

チームTech-ONCはTNP部員かつ、同じ競技プログラミングバイト先の三人で構成されています。
思考力・実装力担当の我らが部長!こしょう!
C++の魔法使い!サバ!
手広無力おじさん!ガナリヤ!
の三人です。
このチームの特徴として

  • 普段アルバイトで、競技プログラミング問題制作を行っている
  • 得意なことがそれぞれ違い、バランスが取れている
  • 三人共コーディングを担当できる
  • いい意味でも悪い意味でも、そこまで競技プログラミングコーディング力が離れていない(他チームは、一人だけ無茶苦茶強いところが多かったりする)

という点があります。
僕が誘わせていただき、引き受けていただきて本当に嬉しかったです!


参加記

事前準備

統計の授業を三人で抜け出してご飯を食べる。
チョコレートがおいしかった。
その後、コーディング場に移動し、それぞれマクロや本の準備をしていた。
その間、サバがVisualStudio設定RTAしてて面白かったです、来年は僕も設定できるようになりたい

16:10頃、監督の先生が到着(本当に引き受けていただきありがとうございます!)
雑談をしつつ、そわそわしながら開始を待つ。
  

ICPC予選開始

16:30から予選開始。
サバニキが印刷をぶん回しつつ、僕がA問題の紙を読み、こしょうがB問題の紙を読み始めました。
その間、サバがVisualStudioの設定やマクロの準備をしており、縁の下の力持ちでした!(またnext_combinationの実装もしてもらってしまった・・・来年までにはもっと簡単な実装にします・・・)サバありがとう!

A問題 所得格差は、N人の合計の平均を取って、平均より小さい人数を数えるだけの問題で非常に簡単でやるだけでした。年々A問題は簡単になっている気がする・・・
ハラハラしつつ、doubleのガバに気をつけてAC

  

B問題とC問題

A問題を解いた後、こしょうがB問題へ。
僕とサバでC問題に移動。

こしょうにきが解いている間、C問題を二人で話し合う。
C問題 みなとハルカス

C問題は、整数bが与えられ、1~Nまでの中で連続した整数の和がbに一致する中で、最長のものを出力せよという問題でした。
二人で話し合った結果、部分累積和で10^8までぶん回すか、しゃくとり法で実装するかの二択になりました。
ここで壮大なミス。
絶対に部分累積和じゃ通らないのに、部分累積和の案を採用。ふたりともしゃくとり法はあまりお得意なお気持ちではないため、部分累積和に逃げてしまった・・・、このミスが無ければDの実装が間に合ったかもしれない(申し訳ない)

間違った部分累積和の実装が行けそうになったとき、こしょうの実装でエラーが発生していた模様。
コードを印刷してもらって、エディタを空けてもらって入れ替わりで僕が嘘解法を実装。
ちなみに、今回のB問題はCよりずっと難しかったようで、さらっと解いてるこしょうやっぱやばい。

嘘解法のCを実装した僕
「できた!天才か〜〜〜?」←嘘解法で喜んでいるクズの図
10^9の実装のため、テストケースだけ通して、もう一度こしょうと交代。
こしょうがB問題の添字ミスと、問題文の勘違いに気づいたらしく難なくAC。こしょうにきは、問題文読み間違い以外基本的にすべて通している(すごい(すごい))

その後、こしょうに変わってもらって、投げていたテストケースを見ると、数が合っておらず、嘘解法であったことに気づく(当たり前だよなぁ?)
急いで、しゃくとり法で実装してAC。やっぱ最初からしゃくとり法にするべきでした、チキっちゃだめやね・・・
  

D問題

ここから毎回僕たちが苦戦しているD問題以降パートへ。

サバニキがD問題とE問題に目をつけていて、問題概要や、解き方のコツを教えてもらった。
D問題 全チームによるプレーオフは、サッカーの試合をするとき、すべてのチームの勝敗が一致し、全員で仲良しになる総数は何個あるか?という問題だった。

僕とサバでDはやべえな・・・となり、他の問題をいろいろ見ていた。よくよく考えるとこれが悪手だった気がする。最初からずっとDのみに取り組んでいれば、時間が間に合ったかもしれない(悔しい・・・)

その後、こしょうもDに参戦し、こしょうとサバが解き方の方針を教えてくれた。(5人なら、必ず全てのチームが2勝2敗とか、普段の自分一人のコーディングなら絶対に気づけてない・・・)

その後しばらく三人でDにうなり続け、うだうだ言いながら、意見を出しつつ、next_combinationで1と0の組み合わせを求めれば計算量はあまり増えないということに気づく(正直合ってるか分からん)
よくわからないまま、時間が無いため、僕が突発的に考えた多分正攻法ではない、汚いアイディアを実装することに。
僕とこしょうでペアプロしつつ、サバがnext_combinationの実装をしてくれた(来年までにはもっと分かりやすいライブラリつくる許して・・・)
こしょうとサバのこしょうを借りつつ、ガバガバ実装を行い、時間と戦いつつ、コーディングが完成。
奇跡に祈りつつ、実行したところ、添字エラー。添字エラーを解消している中で、時間になってしまった・・・

  


振り返り

ICPCに参戦してみて、すんごい楽しかったです。
他の人と、問題を解くためのアイディア出し合ったり、ふざけながら問題通すのって、学生のうちしかできない気がする(仕事になると、ふざけることはできない・・・)
また、自分の実装の弱さに気付かされた回でもありました・・・。他の二人の実装がすごい綺麗で、僕のコーディングがかなり汚いので、デバッグしづらくて二人がかなり僕のコードを追うの辛かったと思います。もっと簡潔なコーディングできるよう目指していきたいです。

何はともあれ、すごい楽しかった
来年もこの三人でTech-ONCとして出るという話をした。
来年は三人共、競技プログラミングがうまくなり、僕はAtCoder年内中に青色、来年のICPCまでに黄色になっているはずなので(希望的観測)、来年のチーム名はTech-ONS(O(N^2))でしょうか・・・

何も考えず、今日あったことをそのまま書いているだけで、読みづらいと思います。すいません。
それぐらい楽しかったです
明日はSoundHound頑張ろうと思います!

ガナリヤでした!

テンプレートを見ていくだけ

祝!テンプレート肥大化!

   
   
このブログには僕しか住んでいない気が・・・
にじさんじ箱推しガチ勢ガナリヤです。
今回は、自分の使用しているテンプレートが自分でも管理しきれなくなったため、公開しつつ見直していこうと思います。
この記事の一番下にお借りしたサイトなどを記述させていただきます。


まずは全体のソースコードを貼っていこうと思います。

はえ〜すっごい長い
でも、コンパイルは余裕で通るし、コード読みやすくなるしええやろ!(無謀)

   
少しずつパーツごとに見ていこうと思います!
   


include


//include
//------------------------------------------
#include <vector>
#include <list>
#include <map>
#include <climits>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <queue>

using namespace std;

c++では、includeで使用する関数などのヘッダファイルを取り込んで使用します。
中身の実体であるcppファイルはたいてい別にあって、ヘッダファイルは宣言のみを基本的に行うのですが、標準ライブラリはすべてヘッダファイルに実装しているみたいですね。
   
   

typedef

//typedef
//------------------------------------------
typedef long long LL;
typedef vector<int> VI;
typedef vector<bool> VB;
typedef vector<char> VC;
typedef vector<double> VD;
typedef vector<LL> VLL;
typedef vector<VI> VVI;
typedef vector<VB> VVB;
typedef vector<string> VS;
typedef vector<VLL> VVLL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<int, string> PIS;
typedef pair<string, int> PSI;
typedef pair<string, string> PSS;

long longなど、よく使用する型名や、vectorなどはエイリアスをつけています。
正直あまり使用しないもののほうが多いですな・・・
   
   

数値・文字列

//数値・文字列
//------------------------------------------
inline int toInt(string s) {
    int v;
    istringstream sin(s);
    sin >> v;
    return v;
}

inline LL toLongLong(string s) {
    LL v;
    istringstream sin(s);
    sin >> v;
    return v;
}

template<class T>
inline string toString(T x) {
    ostringstream sout;
    sout << x;
    return sout.str();
}

inline VC toVC(string s) {
    VC data(s.begin(), s.end());
    return data;
}

template<typename List>
void SPRIT(const std::string &s, const std::string &delim, List &result) {
    result.clear();
    string::size_type pos = 0;
    while (pos != string::npos) {
        string::size_type p = s.find(delim, pos);
        if (p == string::npos) {
            result.push_back(s.substr(pos));
            break;
        } else {
            result.push_back(s.substr(pos, p - pos));
        }
        pos = p + delim.size();
    }
}

string TRIM(const string &str, const char *trimCharacterList = " \t\v\r\n") {
    string result;
    string::size_type left = str.find_first_not_of(trimCharacterList);
    if (left != string::npos) {
        string::size_type right = str.find_last_not_of(trimCharacterList);
        result = str.substr(left, right - left + 1);
    }
    return result;
}

template<typename T>
bool VECTOR_EXISTS(vector<T> vec, T data) {
    auto itr = std::find(vec.begin(), vec.end(), data);
    size_t index = distance(vec.begin(), itr);
    if (index != vec.size()) {
        return true;
    } else {
        return 0;
    }
}

#define UPPER(s) transform((s).begin(), (s).end(), (s).begin(), ::toupper)
#define LOWER(s) transform((s).begin(), (s).end(), (s).begin(), ::tolower)

数が多いので一つ一つ見ていきます。

  • toIntは文字列を受け取って数字にして返します。こういうの合ったほうが何かと便利ですね。速度は遅いですが・・・
  • toLongLongはtoIntのLL版
  • toStringは引数を受け取ってStringにして返します。ostringstreamってなんなんですかね・・・
  • toVCは文字列を受け取ってvectorのcharを返します。なんだかんだ変換する必要が多々あるので便利です。
  • TRIM関数は文字列をきれいにして返します。ただ、普通の場合入力は整理されているためあまり使いませんね・・・
  • VECTOR_EXISTSはテンプレートを使用し、vectorを受け取って特定のdataが存在するかどうかを返します。自分でmain内に書けるレベルですが、読みやすくするためよく使用します。
  • UPPERとLOWERは文字列を受け取ってstd::transformで大文字と小文字に変換します。このレベルは普通string型のメソッドにあるべきだと思うんですけど!!!
       
    SPRIT関数はちょっと癖が強いため以下にコードを書いていこうと思います。

    
    int main() {
    
        string str = "abc def gji";
        VS inputs;
        
        SPRIT(str, " ", inputs);
    
        return 0;
    }
    
    

これはSPRIT関数は3つの引数を受取ります。
第一引数は入力文字
第二引数は文字を分割するためのトークン文字列
第三引数は分割された結果を格納するvectorです。
vectorを使用しているので、何個に分割されるか考える必要がなく、自動で返ってくるので便利ですね・・・

   
 

四捨五入


//四捨五入 nLen=小数点第N位にする
//------------------------------------------

//四捨五入
double ceil_n(double dIn, int nLen) {
    double dOut;
    dOut = dIn * pow(10.0, nLen);
    dOut = (double) (int) (dOut + 0.9);
    return dOut * pow(10.0, -nLen);
}

//切り捨て
double floor_n(double dIn, int nLen) {
    double dOut;
    dOut = dIn * pow(10.0, nLen);
    dOut = (double) (int) (dOut);
    return dOut * pow(10.0, -nLen);
}

//切り上げ
double round_n(double dIn, int nLen) {
    double dOut;
    dOut = dIn * pow(10.0, nLen);
    dOut = (double) (int) (dOut + 0.5);
    return dOut * pow(10.0, -nLen);
}

//n桁目の数の取得
int take_a_n(int num, int n) {
    string str = toString(num);
    return str[str.length() - n] - '0';
}

ceil, floor, round関数の拡張のようです。
自分でもまだ仕組みをよく理解していないため、勉強しようと思います。
標準ライブラリの関数より、小数点以下の桁数を指定できるため細かいです。
take_a_nはそのままです。/=10とかするのが面倒なので文字列にしてから取り出してます。

   
   

進数

//進数
//------------------------------------------

//"1111011" → 123
int strbase_2to10(const std::string &s) {
    int out = 0;
    for (int i = 0, size = s.size(); i < size; ++i) {
        out *= 2;
        out += ((int) s[i] == 49) ? 1 : 0;
    }
    return out;
}

//"123" → 1111011
int strbase_10to2(const std::string &s) {
    int binary = toInt(s);
    int out = 0;
    for (int i = 0; binary > 0; i++) {
        out = out + (binary % 2) * pow(static_cast<int>(10), i);
        binary = binary / 2;
    }
    return out;
}

//"ABC" 2748
int strbase_16to10(const std::string &s) {
    int out = stoi(s, 0, 16);
    return out;
}

//1111011 → 123
int intbase_2to10(int in) {
    string str = toString(in);
    return strbase_2to10(str);
}

//123 → 1111011
int intbase_10to2(int in) {
    string str = toString(in);
    return strbase_10to2(str);
}

int intbase_16to10(int in) {
    string str = toString(in);
    return strbase_16to10(str);
}

//123→ "7B"
string intbase_10to16(unsigned int val, bool lower = true) {
    if (!val)
        return std::string("0");
    std::string str;
    const char hc = lower ? 'a' : 'A';     // 小文字 or 大文字表記
    while (val != 0) {
        int d = val & 15;     // 16進数一桁を取得
        if (d < 10)
            str.insert(str.begin(), d + '0');  //  10未満の場合
        else //  10以上の場合
            str.insert(str.begin(), d - 10 + hc);
        val >>= 4;
    }
    return str;
}

//整数を2進数表記したときの1の個数を返す
LL bitcount64(LL bits) {
    bits = (bits & 0x5555555555555555) + (bits >> 1 & 0x5555555555555555);
    bits = (bits & 0x3333333333333333) + (bits >> 2 & 0x3333333333333333);
    bits = (bits & 0x0f0f0f0f0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f0f0f0f0f);
    bits = (bits & 0x00ff00ff00ff00ff) + (bits >> 8 & 0x00ff00ff00ff00ff);
    bits = (bits & 0x0000ffff0000ffff) + (bits >> 16 & 0x0000ffff0000ffff);
    return (bits & 0x00000000ffffffff) + (bits >> 32 & 0x00000000ffffffff);
}


普通の人は用意してないと思うレベルで用意しています。
TechFULの中級編をやり続けるとこうなります。
ハゲるかと思いました。
strbaseは文字列を受け取ってint型を返します。
intbaseはint型を受け取ってint型を返します。
bitcount64の2進数にしたときの1の個数を数える関数のビット演算の仕組みがよくわかっていないので要学習ですね・・・

比較


//comparison
//------------------------------------------
#define C_MAX(a, b) ((a)>(b)?(a):(b))
#define C_MIN(a, b) ((a)<(b)?(a):(b))
#define C_ABS(a, b) ((a)<(b)?(b)-(a):(a)-(b))

c++の標準ライブラリのmin, maxがクソなので使っています。
理由としてはminの片方にlong longなどをぶち込むと反応してくれません。平成アホくさ丸。
ただ、文字列とかぶち込むとC_ABSなどは実行時エラーを吐くので気をつけましょう。

   
   

コンテイナー


//container util
//------------------------------------------
#define ALL(a)  (a).begin(),(a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define SZ(a) int((a).size())
#define EACH(i, c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define EXIST(s, e) ((s).find(e)!=(s).end())
#define SORT(c) sort((c).begin(),(c).end())
#define RSORT(c) sort((c).rbegin(),(c).rend())
#define REVERSE(c) reverse((c).begin(), (c).end())
#define SUMI(obj) accumulate((obj).begin(), (obj).end(), 0)
#define SUMD(obj) accumulate((obj).begin(), (obj).end(), 0.)
#define SUML(obj) accumulate((obj).begin(), (obj).end(), 0LL)
#define UB(obj, n) upper_bound((obj).begin(), (obj).end(), n)
#define LB(obj, n) lower_bound((obj).begin(), (obj).end(), n)
#define BS(v, n) binary_search(ALL(v), (n))
#define PB push_back
#define MP make_pair

   
ここらへんは他の方のテンプレートでもよく見ますね・・・小文字派の方もいらっしゃいますが・・・
大体は見ての通りマクロで、vectorなどのSTLをいじるものです。
マクロとか利用したほうが速度だけでなく、ソースコードがかなり読みやすくなりました。
使ってみると、結構欠かせないものになる気がします。
   
   

入出力



//input output
//------------------------------------------
#define GL(s) getline(cin, (s))
#define INIT std::ios::sync_with_stdio(false);std::cin.tie(0);
#define OUT(d) std::cout<<(d);
#define OUT_L(d) std::cout<<(d)<<endl;
#define FOUT(n, d) std::cout<<std::fixed<<std::setprecision(n)<<(d);
#define EL() std::cout << "\n";
#define SHOW_VECTOR(v) {std::cerr << #v << "\t:";for(const auto& xxx : v){std::cerr << xxx << " ";}std::cerr << "\n";}


入出力で使用するものです。

  • GLはgetlineの略で予め宣言してあったstring変数に一行分格納します。大体使用するときはこのあとSPRIT関数に直結ですね・・・
  • INITは入出力がガバガバに多いときは使用します。ただ、これやってギリギリセーフなときは、どこか計算量がガバガバに多い気がします。
  • OUT, OUT_Lはcoutの「<<」が面倒なので使用しています。
  • FOUTはdouble型の小数を表示するときに、指定桁をnで、表示内容をdで指定することで、○○桁に対応することができます。
  • SHOW_VECTORはvector型をぶち込むことでさらっとアサートで表示してくれます。vector型の中身をさらっと確認したいときにデバッグ用で使用してます。
       
       

REP


//repetition
//------------------------------------------
#define FOR(i, a, b) for(int i=(a);i<(b);++i)
#define RFOR(i, a, b) for(int i=(b)-1;i>=(a);--i)å
#define REP(i, n)  FOR(i,0,n)
#define RREP(i, n) for(int i = n;i >= 0;i--)
#define FORLL(i, a, b) for(LL i=LL(a);i<LL(b);++i)
#define RFORLL(i, a, b) for(LL i=LL(b)-1;i>=LL(a);--i)
#define REPLL(i, n) for(LL i=0;i<LL(n);++i)
#define RREPLL(i, n) for(LL i=LL(n)-1;i>=0;--i)
#define FOREACH(x, v) for(auto &(x) : (v))
#define FORITER(x, v) for(auto (x) = (v).begin(); (x) != (v).end(); ++(x))

これも他の方のテンプレートでもよく見かけますね・・・
大体の内容はこれで書くことができます。
ただ、indexが複雑なときは普通にforで書いたり、正直–iなどのときはRREPで合ってるのか怖いので、forで書いちゃいますね・・・
FOREACHや、FORITERは、STLなどのset,mapなど、indexが扱いづらいものに使用することが多いです。

   
   

math


//math
//--------------------------------------------

//min <= aim <= max
template<typename T>
inline bool BETWEEN(const T aim, const T min, const T max) {
    if (min <= aim && aim <= max) {
        return true;
    } else {
        return false;
    }
}


template<class T>
inline T SQR(const T x) { return x * x; }

template<class T1, class T2>
inline T1 POW(const T1 x, const T2 y) {
    if (!y)return 1;
    else if ((y & 1) == 0) {
        return SQR(POW(x, y >> 1));
    } else return POW(x, y ^ 1) * x;
}


template<typename T>
constexpr T ABS(T x) {
    static_assert(is_signed<T>::value, "ABS(): argument must be signed");
    return x < 0 ? -x : x;
}

//partial_permutation nPr 順列
//first・・最初の数
//middle・・r(取り出す数)
//last・・n(全体数)
template<class BidirectionalIterator>
bool next_partial_permutation(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last) {
    reverse(middle, last);
    return next_permutation(first, last);
}

//combination nCr 組み合わせ
//first1・・最初の数
//last1==first2・・r(取り出す数)
//last2・・n(全体数)
template<class BidirectionalIterator>
bool next_combination(BidirectionalIterator first1, BidirectionalIterator last1, BidirectionalIterator first2,
                      BidirectionalIterator last2) {
    if ((first1 == last1) || (first2 == last2)) {
        return false;
    }
    BidirectionalIterator m1 = last1;
    BidirectionalIterator m2 = last2;
    --m2;
    while (--m1 != first1 && !(*m1 < *m2)) {
    }
    bool result = (m1 == first1) && !(*first1 < *m2);
    if (!result) {
        while (first2 != m2 && !(*m1 < *first2)) {
            ++first2;
        }
        first1 = m1;
        std::iter_swap(first1, first2);
        ++first1;
        ++first2;
    }
    if ((first1 != last1) && (first2 != last2)) {
        m1 = last1;
        m2 = first2;
        while ((m1 != first1) && (m2 != last2)) {
            std::iter_swap(--m1, m2);
            ++m2;
        }
        std::reverse(first1, m1);
        std::reverse(first1, last1);
        std::reverse(m2, last2);
        std::reverse(first2, last2);
    }
    return !result;
}

ガナリヤの情弱ポイントがバレちゃいますね・・・
数学が苦手なら予め用意していればいいだけの話だ!!!成長はしないが!

  • BETWEENはminとmaxの間にデータがあるかboolを返します。TechFULのErrorを避けるのが面倒だったので作りました。
  • SQRは二乗です。
  • POWはxをy回累乗したものを返します。こういうのはmain内にあるとコードが汚くなるのでありがたいです。標準ライブラリより、型の対応が多いためよく使用します。
  • ABSも同様の理由でよく使用します。
  • next_partial_permutationはnPrの順列をvector型などで取り出すために使用します。do while(next_permutation())の形で使用するとvector型の要素が自動で変更されていくため便利です。仕組みはよくわかりません
  • next_combinationは、標準ライブラリから落選してしまったようなので海外文献から探して使用しています。組み合わせを実現し、do whileで使用します。国内のブログなどには、利用例がないため、ちょっとまだ完璧に使い方が分かりきってはないです・・・
       
       

数学法則

   


//numeric_law
//--------------------------------------------

template<typename T>
constexpr bool ODD(T x) {
    return x % 2 != 0;
}

template<typename T>
constexpr bool EVEN(T x) {
    return x % 2 == 0;
}

//最大公約数
template<class T>
inline T GCD(const T x, const T y) {
    if (x < 0)return GCD(-x, y);
    if (y < 0)return GCD(x, -y);
    return (!y) ? x : GCD(y, x % y);
}

//最小公倍数
template<class T>
inline T LCM(const T x, const T y) {
    if (x < 0)return LCM(-x, y);
    if (y < 0)return LCM(x, -y);
    return x * (y / GCD(x, y));
}

//ax + by = 1
//x,yが変数に格納される
template<class T>
inline T EXTGCD(const T a, const T b, T &x, T &y) {
    if (a < 0) {
        T d = EXTGCD(-a, b, x, y);
        x = -x;
        return d;
    }
    if (b < 0) {
        T d = EXTGCD(a, -b, x, y);
        y = -y;
        return d;
    }
    if (!b) {
        x = 1;
        y = 0;
        return a;
    } else {
        T d = EXTGCD(b, a % b, x, y);
        T t = x;
        x = y;
        y = t - (a / b) * y;
        return d;
    }
}

//素数
template<class T>
inline bool ISPRIME(const T x) {
    if (x <= 1)return false;
    for (T i = 2; SQR(i) <= x; i++)if (x % i == 0)return false;
    return true;
}

//素数をtrueとして返す
template<class T>
VB ERATOSTHENES(const T n) {
    VB arr(n, true);
    for (int i = 2; i < SQR(n); i++) {
        if (arr[i]) {
            for (int j = 0; i * (j + 2) < n; j++) {
                arr[i * (j + 2)] = false;
            }
        }
    }
    return arr;
}

// a <= x < b の素数を返す
template<typename T>
VB ERATOSTHENES(const T a, const T b) {
    VB small = ERATOSTHENES(b);
    VB prime(b - a, true);

    for (int i = 2; (T) (SQR(i)) < b; i++) {
        if (small[i]) {
            for (T j = max(2, (a + i - 1) / i) * i; j < b; j += i) {
                prime[j - a] = false;
            }
        }
    }

    return prime;
}

//約数
template<class T>
vector<T> DIVISOR(T n) {
    vector<T> v;
    for (int i = 1; i * i <= n; ++i) {
        if (n % i == 0) {
            v.push_back(i);
            if (i != n / i) {
                v.push_back(n / i);
            }
        }
    }
    sort(v.begin(), v.end());
    return v;
}

//組み合わせ個数
template<typename T>
T NCR(T n, T r) {
    T ans = 1;
    for (T i = n; i > n - r; --i) {
        ans = ans * i;
    }
    for (T i = 1; i < r + 1; ++i) {
        ans = ans / i;
    }
    return ans;
}

//行列
int MATRIZ_CHAIN(VI &p, VVI &s) {
    const static int INF = 1 << 20;
    const int n = p.size() - 1;
    VVI X(n, VI(n, INF));
    s.resize(n, VI(n));
    for (int i = 0; i < n; ++i) X[i][i] = 0;
    for (int w = 1; w < n; ++w)
        for (int i = 0, j; j = i + w, j < n; ++i)
            for (int k = i; k < j; ++k) {
                int f = p[i] * p[k + 1] * p[j + 1];
                if (X[i][k] + X[k + 1][j] + f < X[i][j]) {
                    X[i][j] = X[i][k] + X[k + 1][j] + f;
                    s[i][j] = k;
                }
            }
    return X[0][n - 1];
}

//最長増加部分列
VI LIS(const VI &a) {
    const static int INF = 99999999;
    const int n = a.size();
    VI A(n, INF);
    VI id(n);
    for (int i = 0; i < n; ++i) {
        id[i] = distance(A.begin(), lower_bound(A.begin(), A.end(), a[i]));
        A[id[i]] = a[i];
    }
    int m = *max_element(id.begin(), id.end());
    VI b(m + 1);
    for (int i = n - 1; i >= 0; --i)
        if (id[i] == m) b[m--] = a[i];
    return b;
}

//最長共通部分列 string->toVC
template<typename T>
vector<T> LCS(const vector<T> &a, const vector<T> &b) {
    const int n = a.size(), m = b.size();
    vector<VI> X(n + 1, VI(m + 1));
    vector<VI> Y(n + 1, VI(m + 1));
    REP(i, n) {
        REP(j, m) {
            if (a[i] == b[j]) {
                X[i + 1][j + 1] = X[i][j] + 1;
                Y[i + 1][j + 1] = 0;
            } else if (X[i + 1][j] < X[i][j + 1]) {
                X[i + 1][j + 1] = X[i][j + 1];
                Y[i + 1][j + 1] = +1;
            } else {
                X[i + 1][j + 1] = X[i + 1][j];
                Y[i + 1][j + 1] = -1;
            }
        }
    }
    vector<T> c;
    for (int i = n, j = m; i > 0 && j > 0;) {
        if (Y[i][j] > 0) --i;
        else if (Y[i][j] < 0) --j;
        else {
            c.PB(a[i - 1]);
            --i;
            --j;
        }
    }
    REVERSE(c);
    return c;
}

//コイン C総額 cs使用できるコインの種類
VI money_change(int C, VI &cs) {
    const int INF = 99999999;
    int n = cs.size();
    VI xs(C + 1, INF);
    VI ys(C + 1);
    xs[0] = 0;
    for (int i = 0; i < n; ++i) {
        for (int c = 0; c + cs[i] <= C; ++c) {
            if (xs] > xs + 1) {
                xs] = xs + 1;
                ys] = c;
            }
        }
    }
    VI zs;
    for (int c = C; c > 0; c = ys) {
        zs.push_back(c - ys);
    }
    return zs;
}


   
長すぎぃ!
でも合ったほうが便利だからええやろ(甘え)

  • ODDは奇数かどうか判定します。inlineをつけてないのでつけようかと思います。
  • GCDは引数x, yの最大公約数を算出します。ユークリッドの互除法をしています。
  • LCMは最小公倍数を算出します。ab = GCD(a,b)*LCM(a,b)という法則があるため、GCDで算出した答えを利用してLCMを算出します。
  • EXTGCDはax+by=1となるx,yが格納されます。仕組みがまだ良くわかってないです。
  • ISPRIMEは引数が素数かどうか判定します。一つの数字のみでいいならこちらを使います。
  • ERATOSTHENESは素数のふるいを行います。配列に格納しておいて、素数を見つけるとSQR(n)分まで回すことで素数以外をfalseにすることで早く計算できます。
  • DIVISORは約数を算出してvectorにして返します。n*nのsqrt以内に半分の素数は存在するため、そちらで算出し、i!=n/iで反対側の素数を算出しています。
  • NCRはnCrの意味で組み合わせを算出します。ただいま、先にかけ算を行っており、数がおおきいとオーバーフローしてしまうため、改善が必要かもしれませんね。
  • LISは部分増加列を算出します。ここらへんはよく出るので、どんな仕組みだったからって確認するために記述させていただいてます。
  • LCSは二つの文字列の部分増加列です。もはや辞書的な役割です。
       
       

confirmation

   


//confirmation
//--------------------------------------------

//clear memory
#define CLR(a, b) memset((a), (b),sizeof(a))

//debug
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;


   
メモリーの初期化(配列に限る)や、デバッグで使用するマクロです。
fillをまだマクロで定義してないのでfillも実装しとこうと思います。

   
   
   
  


あ〜すっげぇキツかったぞ〜
自分が以下にライブラリに頼っているかがバレましたね・・・(バレてるんだよなぁ・・・)
マクロを使うと結構楽に、はやく書けますし、よくわからん数学の部分をオーバーラップできます。
自分なりのテンプレートを作って競プロやると、結構楽しいかもしれません。
僕は、結構使えそうなマクロ作ったり探したりする時間が、競プロの中で一番好きです。(こんな人間になってはいけない)

P.S.

かえみと尊い・・・尊くない・・・?

ドメイン超えに一日を費やした話

こんばんは・・・
毎度おなじみガナリヤです!

今回は、NodeJsのクロスドメイン超えの話です。
初めての技術系ブログになるんですかね・・・

宣伝

現在、昔TNPにあったらしいICPC対策室なるものが、再び復活しようとしています。
活動内容としては、競技プログラミングを行い、実装力・アルゴリズム力をつけるというものです。
・・・正直、大学生からプログラミングを初めている身としては、アルゴリズムが世知辛いのじゃぁ〜

そんなこんなで、ICPU対策室復活に向けて、Discordの秋田大学ICPU対策室サーバーを立て、現在競技プログラミングを便利にするBotを製作中です。

問題

DiscordのBotはいろいろなプログラミング言語で作れますが、ガナリヤは現在Javascriptで記述しています。
Javascriptの特徴は何と言っても、クライアント側のブラウザで動くというところです。
最近では、NodeJsというサーバー側で実行するエンジンを使用することで、クライアント側だけでなく、サーバー側までJavascriptで制作出来るようになりました。
もしかしたら、世の中世知辛くないのかもしれないのじゃ・・・

そんなNodeJsとJavascriptで、HackerRankから、一ヶ月後までのコンテスト情報を取得するコマンドを作成しようとしていました。
HackerRankの情報はxml形式で取得できるため

  1. jQueryでxml形式で取得
  2. 取得したxml形式をxml2jsでJSON形式へ
  3. JSONからmomentを使って適切なコンテストのみ取得

という工程で行おうと思っていました・・・

事件発生

jQueryがガバガバでした。
おじさんが、jQueryで外部サイトの情報を取得しようとすると「それ以上はいけない」と、xmlが取得できませんでした。
取得できない理由はクロスドメイン問題にあります。

理想としては上のような状態です。
自分のクライアントとサーバーと、欲しい情報があるサーバーがそれぞれ通信できています。
しかし、最近のjQueryはクソみたいな発展を果たし(最近はほぼ使われなくなってきている)、他のサーバーとの通信が行えず、同じドメインしか通信できなくなりました。
これがクロスドメイン問題です。

改善策

改善策を色々と探した結果最初の改善策は以下のものでした。
1. phpファイルを利用してデータ取得のみをphpで行う。
2. 人力でxml形式を取得しておき、サーバーにためておく。

1の方法はうまく行きませんでした。理由としては、使用しているデプロイ先が基本的にjsのみであり上手に動作しなかったのが原因です。
2の方法は取りたくありませんでした。人力はクソ。さてはウンチだなおめー

結局・・・

npmモジュールでいいのないかなと探していたら、やっぱありました(最初からやr)
こちらのcheerioです。
クロスドメインも、モジュール内でいい感じにうまくやってくれているらしく、非常にありがたいですね・・・
コードは、きれいにしてからあげます・・・////

 

これもうわかんねえな

 改行がうまくwordpress内でされないので改善したい。

「TNPとは?」ページを更新しました!

 こんにちえるえる〜。
 ついに三年生になってしまったガナリヤです・・・
 時間たつの早すぎィ!
 そろそろ技術系も書いていかないといけませんね・・・

 今更かよ!?って言われそうなのですが・・・
 「TNPとは?」ページを更新しました(今更とか言うのは申し訳ないがNG)!!!
 ページの内容は
・TNPの概要
・TNP活動内容
・TNP活動時間
・TNPイベント
 が主な内容ですね!

 だいぶ自分なりにはかしこまって書けたような気がしますね・・・
 ここはブログなのでぶっちゃけトークをしてしまうと、TNPというサークル名の由来としては、先に卑猥な言葉があってから、なんとかうまいことこじつけてTNPという略語がでk・・・
 ・・・ん?誰か来たようだ

 でもまあTNPはアットホームな場所というのはホントのホントですね・・・
 この二年間とても楽しく過ごせています。
 しかし、おおよそのメンバーが淫夢とかアニメ知ってるとかこれもうわかんねえな・・・
 
 更新遅くなって申し訳ありません・・・
 そして何より速さが足りない(更新しろ)。
 というわけで、どんどんページを更新していこうと思います。
 自分がTNPの代として活動出来る最後の年になり、10月を過ぎると老害の仲間入りを果たします。
 残り時間の間に自分のできることを精一杯やっていきたいと思います。
 今週中におおまかなページは作成して、そこから構造やサイトの最適化を図っていこうと思います。
 ここまでお読みいただきありがとうございます!

P.S
 やっぱVTuberだとにじさんじ押しかなーwwwやっぱwwww
 その中だと月ノ美兎が一番好き(聞いてないwww)
 

Steamゲームレビュー「Doki Doki Literature Club」

 さてはアンチだなテメー
 お久しぶりですガナリヤです。
 最近はもっぱらChainer のよくわからん仕様に頭を悩ませています(内部参照が多すぎて、触っててデータが壊れないのか心配)。ゲーム制作は、それぞれのクラス構造で詰まっています(オブジェクト指向はやっぱ難しいんやなって・・・ どこまでオブジェクトを分離して、詳細化するべきか検討がつかない)

 そんなこんなで、なかなかゲーム制作がうまくいかないので、現実逃避にゲームレビューをします(迫真)。たまには更新しないと、多少はね?(技術系で更新せいや)
 今回レビューするのはこれ「Doki Doki Literature Club」(ネタバレは控えております

 

 あらすじとしては
  主人公は、とある高校の男子高校生。幼馴染のSayoriに誘われて、かわいい女の子たち(Yuri, Monica, Natsuki)がいっぱいの文芸部に所属することに。放課後の部活動の時間では、みんなで詩を書いて、お互いに読みあうことで親睦を高め合う。そして、最後の文化祭での詩の発表会を成功させて、新入生を増やすのだ!
 といった内容。

 お値段はなんと無料。このご時世 、無料とは大胆ですよね・・・。サウンドトラックは有料なので、気に入ったらお布施をしよう!(提案)

 2017年の後半に発表されたのですが、瞬く間に人気が上がり、2017年の海外のゲーム賞を、ノベルゲームとしては異例の大賞をとるなど、その人気ぶりが伺えます。
 
 

 このゲームの魅力を上げたらきりがありませんね・・。
 ・女の子がかわいい!!
 ・Sayoriがかわいい!
 ・Yuriがかわいい!
 ・Natsukiがかわいい!
 ・本性現したね
 去年やったゲームの中だと、ダンガンロンパv3ぐらい、もしくはそれ以上驚かされました・・・・。システム面からみても、CGの美しさにしても、ストーリーの構成、伏線の貼り方にしても近年類を見ないノベルゲームだったと思います。
 

 もしDokiDokiLiteratureClub(DDLC)をプレイする場合は、インターネットなどで何一つ検索せず、Steamでインストールを行い、完全初見プレイで行うのがいいと思います。
 検索を行ってしまうと、ちょっとだけ面白さが減ってしまうかななんて思ったり・・・。上にはってあるSteamリンクからインストールしましょう(ステマ)
 元々は英語で制作されたゲームであり、システム上、英語でプレイしたほうがわかりやすいと言いますか、「あっ・・・(察し)」みたいな点もあるのですが、非公式日本語パッチも出ています。
 日本語化パッチリンク
 
 プレイ時間 もあまり長くない(三時間くらいかな?)と思うので休日とかに気が向いたらやってみてください。
 ゲーム創作意欲がすごいわきます。

 最後になりますが
              This game is not suitable for children or those who are easily disturbed.

     Th繝「 y?u f繝r your rea_ing!!

Steamゲームレビュー「FoxHime」

 お疲れ様です!ガナリヤです!

 今日は久しぶりに部室に行ったのですが、まだまだ寒いですね・・・
 しばらくはこれまで通り一人図書館家活動になりそうです・・
温かいところに行きたい・・・

 最近はディープラーニングと塾バイトに勤しんでいるため、あまりゲームが作れていないため、1月にプレイしたゲームの感想を書こうと思います。

その名もFox Hime


 中国制作のゲームであり、日本寄りの絵柄・内容のゲームとなっています。値段も非常にお手頃で買った当時はSteamセール中で100円だったはずです。
 気になるストーリーとしては「自分の守護霊である狐ちゃんと、急に仲良くなった女の子とキャンプに行くぜ!」みたいな感じです。荒削りさがまたいい。
 プレイ時間は6時間ほどで一本道ルートであり、ストーリーが短く、ちょっと感情移入しづらい点がありました。でも、ただただ女の子がかわいい!!!けもみみは良いぞ。

 この頃からバーチャルユーチューバーの「のじゃろり」にもハマっており、自分の新たなジャンルを再発見できたゲームでした。

 最近すごい思うんですけど、アニメとか漫画の男女の急接近ぶりとかすごいですよね・・・。たった一日とかで「ズッ友だよ!一緒にお風呂はいろ!」とうまやらけしかr・・ghnghn..

 また、特徴として非常に読みやすい英語で書かれてました。アメリカの外人兄貴もグーグル翻訳レベルでひもじいって書いてました。中国語のボイスアップデートが欲しいです・・ほしくない?

 久しぶりに更新をしました。
 時間を見つけ次第、サイトの隅々の更新を新入生が入る4月に向けて行っていきたいと思います。

MMD4MecanimのMacでのエラーについて

 
 お疲れ様です。ガナリヤです!
 UnityでMMDモデルを使用したいと考えたのですが、なかなかうまく行かなかったため、忘れないうちにこちらに記しておこうと思います。

UnityでMMDモデルを読み込む方法

①Blenderで一度取り込み,.blendファイルを読み込む
 MMDのモデルデータは、pmx形式になっています。
 しかし、Unityで対応しているモデルデータ形式は
 ・fbxファイル(Unityではこれが普通。ただし、マテリアル、テクスチャが読み込まれないなどめんどくさい)
 ・blendファイル(Blender)
 が主にあります。以前Splatoonプロジェクトを行ったときはfbx形式を使用していました。
 今回は、BlenderでMMDモデルを取り込むため、fbx形式、blend形式のどちらでも良かったのですが、なぜかどちらもうまく行きませんでした。
 fbx形式では、マテリアルとテクスチャが取り込まれず
 blend形式では、マテリアルとテクスチャは取り込まれたものの、色の設定が行われておらず、表示位置から少しずれていました。
 Unity2017の最新版で、うまく対応してないのかもしれません。
 今回はこの方法でうまくいかないため、新たな方法②を使用しました。

②MMD4Mecanimを使用する
 MMD4MecanimはNoraさん(@Stereoarts)が開発した、Unity上でMMDモデルであるpmx形式を直接読み込み、fbx形式に出力できるというすごいツールです!
 
 なお、MMD4Mecanimの導入は他のサイトさんをご利用ください。(うまくかけないため)

 自分もMMD4Mecanimを導入したのですが
 Processボタンを押してもうまく行きませんでした。
 
 そこで、うまくいかない理由は以下のとおりであると考えました。
 「自分の開発環境がMacであり、MMD4MecanimはWindowsの機能を利用するため、うまくいかない」

 そこで、上の画像にもあるのですが、「Wine」というLinux/Macで動作するアプリを使用しました。これは、Mac上で、Windowsのソフト、機能を使用することができるというアプリです。
 このWineをインストールしてもうまく行きませんでした。(後に確認したところ、Wineはなくても、最新のMMD4MecanimはMacでも動作するようです。) 

 じゃあなんで行かないのじゃぁ・・・(のじゃロリ風)

 圧倒的壁に立ちはだかったため、開発者であるNoraさんに質問をさせていただきました。
 質問をさせていただいたところ、UnityのEditorログにエラーが載っているとのことでした。

 確認をしてみたところ
「 Reason: Incompatible library version: pmx2fbx_275 requires version 8.0.0 or later, but libiconv.2.dylib provides version 7.0.0
Processed pmx2fbx.」
 という表記があり、libiconv.2.dylibという動的ライブラリのバージョンが古いため作動していないということでした。

 libiconvってなんやねんって思い、検索してみたところ、要約すると、文字列の文字コードを変換するライブラリでした。
 ・・・・・なるほど、よくわからん。
 
 とりあえずlibiconv.2.dylibのバージョンが8になればいいやと思い、色々とサイトを調べ、継ぎ接ぎ継ぎ接ぎ実行した結果うまく行きました。
 方法としては
1.XCodeのコマンドラインツールが必要なため、インストール
2.macportsというパッケージ管理ツールをダウンロードしてインストール(homebrewに近いものです)
3.ターミナルに「port rev-upgrade」と入力し、libiconvをアップデート(うまくいかない場合は先頭に sudo とつけて、管理者権限で行ってください)
4.ターミナルに 「brew install libiconv」と入力し、libiconvをこれでもかとアップデート

 上の方法で、自分でもよくわかっていませんが、なんかうまくいきました。うまく行った結果は以下の画像です。

 
 かばんちゃんかわいいよハァハァ・・・

 よくよく考えたら明日テストでした。
 どうしましょう。以上、ガナリヤでした

【ガナリヤ版】ニコニコ動画を通して2017年を振り返る

お久しぶりです!ガナリヤです!
一日中バイトで疲れて精神的疲労がやばくて勉強したくないんで、自分なりの一年を振り返りをしていこうと思います。
ガナリヤの娯楽はだいたいニコニコ動画・・・
2017年のガナリヤなりのニコニコ動画を振り返っていきたいと思います

【2017年1月】

1月のニコニコ動画の伸びた動画といえば
・小林さんのメイドラゴン
・けものフレンズ第一話
・スーパーマリオサンシャイン池崎
・その心わらってるねおばさんのモノマネをする男の子
・BBEMYBABY
などがありましたね!
この頃から少しBBEMYBABYが下火になり、逆にアイマス一人合作全盛期の時期を迎えていました。
また岡山ドバーランドの人気がどんどん増加した時期でもありましたね。
振り返ってみると
「あのアニメからもう一年経っとるやん!?」
って、ガブリールドロップアウトを見て思いました。時が経つというものは早いものですね。
塾講師アルバイトを初めて一年になるのも早いものです・・・

【2017年2月】

2月のニコニコ動画の中でガナリヤなりのブーム動画は
・けものフレンズ
・クッキー☆
・淫夢バース
ですね・・・。
本当にこの時期は我らTNPの部員全員けものフレンズ一色に染まっていましたね・・
会話の半分が、淫夢語録とけもふれ語録まみれやったんや・・
やはりけものフレンズは偉大、はっきりわかんだね。
また、クッキー☆では、着々と世代交代を果たしていた時期でしたね。
唐突のHSIブームから、NYN、偽NYN姉貴ブームに変わっていたのはこの頃だった気がします。
この頃のシャドウバースはまだ面白かった

【2017年3月】

 早速、なぜ一年分振り返ろうとして、ブログを書いているのか後悔してきました・・なかなか時間かかりますね・・
 3月のニコニコ動画の中でガナリヤなりのブーム動画は
・けものフレンズ第十一話
・けものフレンズMAD
・子供の笑顔で飯を食うHIKAKIN
・バルーン
です。
 やはり、けもふれ一色。けもふれで脳を溶かし、テストすっぽかすフレンズがいた気が・・・これももういい思い出ですね・・
 また、第11話のけものフレンズ終了後のTNPは活動に手がつかず(いつも通りやろ)、ただただ最終回を予想し、「たつき監督を信じろ」と祈る時間が続きました
 HIKAKINに至っては普段通り動画を取っているだけなのに、周りのYoutuberが自滅するせいで、音の出るゴミから、唯一神として崇められてて草が生えました。子供を笑顔にして食う飯はうまいか?(うまいんだよなぁ・・・・)
 また、ボカロ界隈ではバルーン兄貴とナユタン星人兄貴の人気がうなぎのぼりでした。でも僕はラマーズ兄貴がいちばん好きです愛してる

【2017年4月】

4月のニコニコ動画の中でガナリヤなりのブーム動画は
・けもふれMAD
・エロマンガ先生
・ゲームセンター東方
・パンジャンドラム
・ボカロ熱再燃
です。
 この時期はけもふれMAD一色でしたね・・・。MMDで自分で続きを作っていまうフレンズ、ディズニーに喧嘩を売るフレンズ、MADを作るフレンズ、歌のうまいフレンズなどたくさんのフレンズが誕生しました。僕達TNPでのカラオケでも、ジャパリパークが締めの曲として定番化することになりました。
 ゲームセンター東方がまた投稿されたのがとても嬉しかったです。やっぱ、特にないです(投稿者)さんの作る動画はすごいですね・・USSR
 ボカロにも再燃していた時期ですね。昔の曲や、最近の曲を再び聞く頻度がかなり上がったポイントです。

 やんばるさんの動画の新作いつ来るんだろう・・・もう四年ほど立った気がする・・・

【2017年5月】

5月のニコニコ動画の中でガナリヤなりのブーム動画は
・XXハンター
・レオモン完結
・ごちうさの敗北
・はやくそれになりたい!
・ずんだホライズン
・Eve
・kemu
です。
 「絶対裏切りヌルヌル!」ゆうき語録が流行った時期でした。他の語録に比べると、使用される頻度が減るのが比較的身の回りでは早かった気がします。汎用性が他と比べてしまうと少ないのが原因かと思われます。場所によってはなかなか効きますね。
 レオモンのコイキングシリーズも完結しましたね。中学生のころから見ていたのでかれこれ八年間ほどレオモンさんの動画を見てきたのかもしれません。里親かな?
 けもふれがゴチうさを超えた時期でもありました。けもふれの民とごちうさの民は喧嘩しないちくり〜
 ずんだホライズンも自分のバイブルとなる作品となりました。最初は、なんやこれ?って見てましたが見れば見るほど、味の滲み出る作品でした。ずんだネキ
 ボカロ界隈ではキノシタさんの「はやくそれになりたい!」、Eveさんの台頭、kemuさんの帰還など色々と変化が訪れた時期でした。
 
 クッキー☆では新しいブームが訪れようとしていました・・・

【2017年6月】

6月のニコニコ動画の中でガナリヤなりのブーム動画は
・よいクラサバイバル
・ボーちゃん
・PUBG
・ゆゆうた
・デレステの課金反映
・止まるんじゃねえぞ・・・
・NYN姉貴、イースター☆
です。

 よいクラがニコニコ動画にも投稿され「いきがい」コメで埋め尽くされたのもすでに一ヶ月前なのですか・・・
 溺れるボーちゃんも流行りましたね〜。TNPでも事あるごとに「ボ’’’’’’’’助けてしん’’’’ちゃん’’’’’」言ってましたね。流行に敏感すぎぃ!
 PUBG動画も流行ってきました。個人的に好きなPUBGは、「公害ゆかり」という、公開チャット上にコンギョとかを大音量で流すというプレイ動画でした。
 ゆゆうた兄貴も非常に人気が急上昇し、すぐ会えるアイドルとして、ランキングに何度も乗ってました。
 NYN姉貴、偽NYN、イースター☆の人気も急上昇してきました。基本的にクッキー系列は誰かが面白い動画を作る。なぜかブームになる。という流れを、次から次へと対象を移して行われてきてるように感じます。今は、MG姉貴兄貴がブームになるのではと予想しています。

【2017年7月】

いよいよ、夏休みの手前として、期末テストの勉強を始めた時期だったでしょうか・・
7月のニコニコ動画の中でガナリヤなりのブーム動画は
・アホガール
・砂の惑星
・ゆゆうた
・ボーちゃん
・バジリスクタイム
・異世界スマホ
・らきすた一挙放送
です。
 アホガール地獄。
 ハチさんから久しぶりのボカロ投稿ということで砂の惑星があがりました。古参厨としておじさん頑張っちゃうぞ〜
 バジリスクタイムも流行ってました。好きな動画は、小さいこどもがおどったあと、例の黒人が踊る動画ですね。「仕上げはお父さん」コメで一時間ほど笑ってました。
 異世界スマホが少しずつ台頭してきた時期でもありました。全話見たはくらい兄貴には脱帽です。異世界スマホは、いや〜きついっす
 らきすた一挙放送があったのでみてみました。くっそ面白かったです。やっぱ古典も見ていこうと改めて思いました。

【2017年8月】

8月のニコニコ動画の中でガナリヤなりのブーム動画は
・股間強打新宝島少年
・wowaka
・全力☆Summer
です。
 比較的安定した時期でした。
 ただただクッキーと淫夢、MAD動画、ましおのドリクラ実況を見ていた時期でした。

【2017年9月】

9月のニコニコ動画の中でガナリヤなりのブーム動画は
・拳で
・異世界オルガ
・たつき監督
・steam糞ゲ祭
です。
 異世界オルガで心を癒やしてました。異世界スマホの第十一話だけをみてみました。感想は、ないです。
 一大ニュースとしてたつき監督が、けもふれ2期制作から離れるということがありました。KADOKAWA許すまじ
 steam系のクソゲー実況、RTAが増えてきた時期でしたね。

【2017年10月】

10月のニコニコ動画の中でガナリヤなりのブーム動画は
・今カウンターしようとしてた?
・勇者のくせになまいきだVR ムスメちゃん
・拳で抵抗する21歳ゲーム
・オルガMAD
です。
 ここらへんでVRに非常に興味が湧いた時期でした。
 学生自主プロジェクト、やりたいけど、どれをやろうか・・・・
 

【2017年11月】

11月のニコニコ動画の中でガナリヤなりのブーム動画は
・ニコニコ動画(く) 延期
・ゆゆうた家凸
・かものはし
・でかいけつゾロリ完結
・ジャガーマンシリーズ
・品性を疑う
・ブレンドS
です。
 ニコニコ動画(く)のアップデートが延期されました。この時点で嫌な予感はしていました。でもあそこまで使いづらいアップデートのみだったとは思ってませんでした。アーキレソ
 ゆゆうたの家凸が続いた時期でもありました。家凸ロシア人バジリスクタイム大好きゆゆうた兄貴大好き愛してる
 でかいけつゾロリ完結。ゾロるという動詞を作った男の最後の動画は、見どころ山しかありませんでした。毎秒投稿しちくり・・
 かものはしの動画もこれまで以上に見始めた時期でもあります。
 
 ジャガーマンシリーズが流行ったのもこの頃からです。最初は毎朝ゆっくり見ていたのですが、ある時点から急に指数関数的に増加し、追いつけないほどの量になってきました。
 半沢直樹パロディと、チベスナマン、島唄MADが今のところ記憶に一番残っています。年末にもっかいジャガーマンシリーズを見直そうと思います。

【一年を通して】

 2017年のニコニコ動画を振り返ると「けものフレンズ」「例のアレ」「歌ってみた」に尽きると思いました。
 「歌ってみた」が2017年のニコニコ動画に入る理由はなんやねん?ってなりそうですが、理由としてはニコニコ広告に尽きると思います。
 僕はたまに見る感じなのですが、ニコニコ広告チケットが多く配布されているため、ニコニコランキングがだいたい歌ってみたが多くなってた記憶があります。
 ニコニコ動画に求めるアップデートとしては
・特定タグのみのランキング機能
・特定タグを抜いたランキング機能
・広告を抜いたランキング機能
・ニコルくん復活
・画質向上
・無名投稿者でもランキングに上がってくるような工夫
といったところでしょうか。
 嫌というわけではないのですが、歌ってみたばっかりのランキングになってしまうと、新しい動画を探すためにタグ、キーワード検索をわざわざやんないといけないのでめんどくさいんですよね・・・
 ニコニコ動画はどこを目指しているんだ・・・

 なんだかんだニコニコ動画が好きなので一生住み続けていくと思います。
 2018年は何が流行るのか、楽しみで仕方ありません。

 2017年もあともう少し、バイトと勉強をしっかりやっていこうと思います。
 ガナリヤでした!