nは0以上10^18以下の整数とする。例えば123を入力すると124が出力される。下のソースコード中のコメントでi桁の整数と言ったとき、最上位の桁(i-1桁目)が0でもよいとする。最下位ビットを0桁目と呼んでいる。
#include <bits/stdc++.h> using namespace std; using ll = long long; int main() { ll n; cin >> n; constexpr int N = 60; // dp[i][0] : 2進法でi桁の非負整数で「nの下i桁」以下のものの個数 // dp[i][1] : 2進法でi桁の非負整数で上記以外のものの個数 ll dp[N + 1][2] = {}; dp[0][0] = 1; // nの下0桁は0、0桁の非負整数は0のみ、よって該当するものは1個 // 代えて dp[0][1] = 1 とすればn未満の非負整数の個数がわかる for (int i = 0; i < N; i++) { for (int j = 0; j < 2; j++) { for (int d = 0; d < 2; d++) { // i桁目に付ける数字 // 「nの下i+1桁」以下とそれ以外、どちらへ遷移するか int j1 = d + j > (n >> i & 1); // dがnのi桁目より大きければ「nの下i+1桁」より大きくなることが確定 // jが1であれば、dがnのi桁目と等しくても大きくなる dp[i + 1][j1] += dp[i][j]; } } } cout << dp[N][0] << endl; return 0; }
10進法で考える別解。入力は文字列としてsで受け取っている。
#include <bits/stdc++.h> using namespace std; using ll = long long; int main() { string s; cin >> s; int n = s.size(); ll dp[20][2] = {}; dp[n][0] = 1; for (int i = n - 1; i >= 0; i--) { for (int j = 0; j < 2; j++) { for (int d = 0; d < 10; d++) { int j1 = d + j > s[i] - '0'; dp[i][j1] += dp[i + 1][j]; } } } cout << dp[0][0] << endl; return 0; }