topcoder srm 575 div1
阿新 • • 發佈:2018-12-22
problem1 link
如果$k$是先手必勝那麼$f(k)=1$否則$f(k)=0$
通過對前面小的數字的計算可以發現:(1)$f(2k+1)=0$,(2)$f(2^{2k+1})=0$,(3)其他情況都是1
這個可以用數學歸納法證明
problem2 link
假設字串的總長度為$n$
首先,設$x_{k}$為位置$i$經過$k$ 次交換後仍然在$i$的概率,那麼在其他位置$j(j\ne i)$的概率為$\frac{x}{n-1}$.可以得到關於$x_{k}$的轉移方程$x_{0}=1, x_{k}=x_{k-1}*\frac{C_{n-1}^{2}}{C_{n}^{2}}+(1-x_{k-1})*\frac{1}{C_{n}^{2}}$
計算出了$x_{k}$之後。對於$[1,n]$的某個位置$i$,其對答案的貢獻為$G(i)=(x_{k}*P+\frac{x_{k}}{n-1}*(T-P))*S_{i}$
其中$S_{i}$表示位置$i$的數字。$P$表示任意選一個區間包含$i$的概率,$P=F_{i}=\frac{2i(n-i+1)}{n(n+1)}$,而$T=\sum_{i=1}^{n}F_{i}$
problem3 link
code for problem1
#include <string> class TheNumberGameDivOne { public: std::string find(long long n) { if (IsFirstWin(n)) { return "John"; } return "Brus"; } private: bool IsFirstWin(long long n) { if (n == 1 || n % 2 == 1) { return false; } int c = 0; while (n % 2 == 0) { ++c; n /= 2; } if (n == 1 && c % 2 == 1) { return false; } return true; } };
code for problem2
#include <string> #include <vector> class TheSwapsDivOne { public: double find(const std::vector<std::string> &seq, int k) { int n = 0; int sum = 0; for (const auto &e : seq) { n += static_cast<int>(e.size()); for (char c : e) { sum += c - '0'; } } auto Get = [&](int t) { return 2.0 * t * (n - t + 1) / n / (n + 1); }; double sum_rate = 0.0; for (int i = 1; i <= n; ++i) { sum_rate += Get(i); } double p = 1.0 * (n - 2) / n; double q = 2.0 / n / (n - 1); double x = 1.0; for (int i = 1; i <= k; ++i) { x = p * x + q * (1 - x); } double result = 0; int idx = 0; for (const auto &e : seq) { for (size_t i = 0; i < e.size(); ++i) { ++idx; int d = e[i] - '0'; double r = Get(idx); result += (x * r + (1 - x) / (n - 1) * (sum_rate - r)) * d; } } return result; } };
code for problem3