一見すると かかるように思えるかもしれない。でも実は になる。
問題概要
個の整数 が与えられる (それぞれ 0 または 1)。このとき、 個の 0-1 変数 の値を、以下の条件を満たすように定めよ。
- 各 に対して、 を 2 で割ったあまりが に一致する
制約
考えたこと
たとえば のときはこんなふうになる。
これを見て思うことは、 の順に自動的に決まっていきそうだということ。まず が決まり、それが決まると
より が決まり、
より が決まり、
より が決まる。これは一般にも成り立ちそうだ。
計算量解析
以上から一般に、 が決まっているときに
とすればよいことがわかる。しかしこの解法は一見すると の計算量となりそうな気がしてしまう。
でもよくよく考えてみよう。 を求めるのに参照する の個数は となるのだ。そしてこれを について合計すると
となるのである。一般に
を調和級数と呼び、 程度の発散スピードであることが知られている (証明は の積分が であることから来る)。
コード
実装上は のところは
に置き換えても OK。mod. 2 の世界では「引き算」も「足し算」も一緒だからだ。
#include <bits/stdc++.h> using namespace std; int main() { int N; cin >> N; vector<int> A(N+1); for (int i = 1; i <= N; ++i) cin >> A[i]; vector<int> x(N+1, 0); for (int i = N; i >= 1; --i) { int sum = A[i]; for (int j = i*2; j <= N; j += i) sum += x[j]; x[i] = sum % 2; } vector<int> res; for (int i = 1; i <= N; ++i) if (x[i] == 1) res.push_back(i); cout << res.size() << endl; for (auto v: res) cout << v << " "; cout << endl; }