#include /* 以下拾ってきたテンプレート */ //// bit //// #ifdef _MSC_VER #ifdef _WIN32 inline unsigned int __builtin_ctz(unsigned int x) { unsigned long r; _BitScanForward(&r, x); return r; } inline unsigned int __builtin_clz(unsigned int x) { unsigned long r; _BitScanReverse(&r, x); return 31 - r; } inline unsigned int __builtin_ffs(unsigned int x) { unsigned long r; return _BitScanForward(&r, x) ? r + 1 : 0; } inline unsigned int __builtin_popcount(unsigned int x) { return __popcnt(x); } #ifdef _WIN64 inline unsigned long long __builtin_ctzll(unsigned long long x) { unsigned long r; _BitScanForward64(&r, x); return r; } inline unsigned long long __builtin_clzll(unsigned long long x) { unsigned long r; _BitScanReverse64(&r, x); return 63 - r; } inline unsigned long long __builtin_ffsll(unsigned long long x) { unsigned long r; return _BitScanForward64(&r, x) ? r + 1 : 0; } inline unsigned long long __builtin_popcountll(unsigned long long x) { return __popcnt64(x); } #else inline unsigned int hidword(unsigned long long x) { return static_cast(x >> 32); } inline unsigned int lodword(unsigned long long x) { return static_cast(x & 0xFFFFFFFF); } inline unsigned long long __builtin_ctzll(unsigned long long x) { return lodword(x) ? __builtin_ctz(lodword(x)) : __builtin_ctz(hidword(x)) + 32; } inline unsigned long long __builtin_clzll(unsigned long long x) { return hidword(x) ? __builtin_clz(hidword(x)) : __builtin_clz(lodword(x)) + 32; } inline unsigned long long __builtin_ffsll(unsigned long long x) { return lodword(x) ? __builtin_ffs(lodword(x)) : hidword(x) ? __builtin_ffs(hidword(x)) + 32 : 0; } inline unsigned long long __builtin_popcountll(unsigned long long x) { return __builtin_popcount(lodword(x)) + __builtin_popcount(hidword(x)); } #endif // _WIN64 #endif // _WIN32 #endif // _MSC_VER /* コピペテンプレートおわり */ inline unsigned long long popcount(unsigned long long x) { return __builtin_popcountll(x); } #define BITS_LOWER (10) using namespace std; typedef unsigned long long ull; struct Point { ull need2overflow; ull next; }; // problems/402 int main() { ull n; cin >> n; int i=0; ull tmp = n; while (true) { if(tmp>>1 == 0) break; tmp = tmp >> 1; i++; } ull nbits = i; ull bits_upper = nbits >= BITS_LOWER ? nbits - BITS_LOWER : 1; bits_upper++; // 行き過ぎの検知のために多少オーバーすることがあるため、一桁多く取る //cout << bits_upper << endl; // if (npc <= BITS_LOWER) {普通に計算;} // 大きい値を諦めてみる if (bits_upper > 24) { cout << -1 << endl; return 0; } Point** P = new Point*[bits_upper]; for (int i = 0; i < bits_upper; i++) { P[i] = new Point[1 << BITS_LOWER]; } // 下BITS_LOWERビットについて調べる for (int i = 0; i < bits_upper; i++) { for (ull ii = 0; ii < 1 << BITS_LOWER; ii++) { if (i == 0 && ii == 0) continue; ull bit = ii; ull max = 1 << BITS_LOWER; ull c = 0; while (true) { c++; bit += (i + popcount(bit)); if (bit >= max) { bit -= max; break; } } P[i][ii].need2overflow = c; P[i][ii].next = bit; //cout << "[" << i << "][" << ii << "]: " << P[i][ii].need2overflow << ", " << P[i][ii].next << endl; } } ull result = -1; ull upper = 0; ull lower = 1; ull count = 1; ull current_upper = upper; ull current_lower = lower; ull current_count = count; ull upc = popcount(upper); while (true) { current_upper = upper; current_lower = lower; current_count = count; upc = popcount(upper); count += P[upc][lower].need2overflow; lower = P[upc][lower].next; upper++; ull pos = (upper << BITS_LOWER) + lower; if (pos >= n) { // 行き過ぎ // 一つ戻す count = current_count; upper = current_upper; lower = current_lower; pos = (upper << BITS_LOWER) + lower; // 普通に計算する while (true) { if (pos == n) { result = count; break; } else if (pos > n) break; pos += popcount(pos); count++; } break; } } cout << result << endl; return 0; }