Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <cstring>
- #include <cassert>
- #include <iostream>
- #include <algorithm>
- #include <vector>
- #include <set>
- #include <tuple>
- #define FOR(i, a, b) for (int i = (a); i < (b); ++i)
- #define REP(i, n) FOR (i, 0, n)
- #define _ << " _ " <<
- #define TRACE(x) cerr << #x << " = " << x << endl
- #define debug(...) fprintf(stderr, __VA_ARGS__)
- //#define debug
- //#define TRACE(x)
- using namespace std;
- typedef long long llint;
- const int MAXN = 10000010;
- const int A = 1103515245;
- const int B = 12345;
- const int M = (1LL<<31) - 1;
- int n, r;
- int a[MAXN];
- // string ans[MAXN];
- // string U[2*MAXN], D[2*MAXN];
- llint sum[110];
- __int128 p10[110];
- __int128 S;
- inline bool cmp(const string &s1, const string &s2) {
- if (s1.size() != s2.size()) return s1.size() < s2.size();
- return s1 < s2;
- }
- inline string merge(__int128 U, __int128 D) {
- string s1, s2;
- while (U) { s1.push_back(char(U % 10 + '0')); U /= 10; }
- reverse(s1.begin(), s1.end());
- while (D) { s2.push_back(char(D % 10 + '0')); D /= 10; }
- reverse(s2.begin(), s2.end());
- return s1 + s2;
- }
- inline string max_num(const string &s1, const string &s2) {
- return cmp(s1, s2) ? s2 : s1;
- }
- inline int len(__int128 x) {
- int ret = 0;
- while (x) { x /= 10; ++ret; }
- return ret;
- }
- tuple<__int128, __int128, int> solve(int u) {
- if (u > n) return make_tuple(0, 0, -1);
- __int128 U1, U2, D1, D2;
- int L1, L2, L;
- __int128 U, D;
- if (2*u <= n) {
- tie(U1, D1, L1) = solve(2*u);
- tie(U2, D2, L2) = solve(2*u+1);
- if (u < 1000) {
- string ans = max_num(merge(U1, D2), merge(U2, D1));
- int sz = int(ans.size());
- REP (j, sz) sum[j] += ans[sz-j-1]-'0';
- } else {
- __int128 ans, tmp1, tmp2;
- tmp1 = U1 * p10[L2 + 1] + D2;
- tmp2 = U2 * p10[L1 + 1] + D1;
- ans = max(tmp1, tmp2);
- S += ans;
- }
- U = max(U1, U2);
- if (D1 > D2) { D = D1, L = L1; } else { D = D2, L = L2; }
- } else {
- U = D = 0;
- L = -1;
- }
- U = U * 10 + a[u];
- D = a[u] * p10[L + 1] + D;
- // U.push_back(char(a[u]+'0'));
- // D.insert(0, 1, char(a[u]+'0'));
- return make_tuple(U, D, L + 1);
- }
- int main(void) {
- memset(a, -1, sizeof a);
- scanf("%d%d", &n, &r);
- for (int i = 2; i <= n; ++i) {
- r = ((llint)A*r + B) & M;
- a[i] = ((r >> 16) % 9) + 1;
- }
- p10[0] = 1;
- FOR (i, 1, 61) p10[i] = 10 * p10[i-1];
- // for (int i = n; i >= 1; --i) {
- // ans[i] = max_num(U[2*i] + D[2*i+1], U[2*i+1] + D[2*i]);
- // int sz = int(ans[i].size());
- // for (int j = 0; j < sz; ++j)
- // sum[j] += ans[i][sz-j-1]-'0';
- // if (i == 1) break;
- // U[i].push_back(char(a[i] + '0'));
- // D[i].insert(0, 1, char(a[i] + '0'));
- // U[i/2] = max_num(U[i/2], U[i]);
- // D[i/2] = max_num(D[i/2], D[i]);
- // }
- solve(1);
- __int128 tmp = 0;
- REP (i, 100) {
- tmp += sum[i];
- sum[i] = llint(tmp % 10);
- tmp /= 10;
- }
- tmp = S;
- for (int i = 0; i < 101; ++i) {
- tmp += sum[i];
- sum[i] = llint(tmp % 10);
- tmp /= 10;
- }
- int start = -1;
- for (int i = 101; i >= 0; --i)
- if (sum[i] != 0) {
- start = i;
- break;
- }
- if (start == -1) {
- printf("0\n");
- } else {
- for (int i = start; i >= 0; --i)
- printf("%lld", sum[i]);
- printf("\n");
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement