一个整数perfect集合满足性质:集合中任意两个整数的异或和仍在这个集合中。
求最大数不超过K的perfect集合的个数。
每个集合都是一个线性的向量空间。。可以通过完全的高斯消元得出该空间的基底。。从高位到低位按基底DP。。
DP[now][num][upper]表示K从左往右第now位空间向量个数为num且集合中最大值是否为K的前now位的基底个数。。。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <cassert>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#define RD(x) scanf("%d", &x)
#define REP(i, n) for (int i=0; i<(n); i++)
#define FOR(i, n) for (int i=1; i<=(n); i++)
#define pii pair<int, int>
#define mp make_pair
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
using namespace std;
#define N 50
#define M 22222
#define eps 1e-9
#define pi acos(-1.0)
#define inf 0XFFFFFFFll
#define mod 1000000007ll
#define LL long long
int K;
LL dp[N][N][2];
LL c[N][N];
int main() {
REP(i, N) REP(j, i + 1) {
if (j == 0 || j == i)
c[i][j] = 1;
else
c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod;
}
RD(K);
dp[31][0][1] = 1;
for (int i = 31; i > 0; --i) {
for (int j = 0; j <= 30; ++j) {
for (int k = 0; k < 2; ++k) {
// add new 1 in a new vector
if (!(k == 1 && (K >> (i - 1)) % 2 == 0)) {
int nk = (k == 1 && (K >> (i - 1)) % 2 == 1) ? 1 : 0;
dp[i-1][j+1][nk] += dp[i][j][k];
dp[i-1][j+1][nk] %= mod;
}
// add new 1 in old vectors even
int nk = (k == 1 && (K >> (i - 1)) % 2 == 0) ? 1 : 0;
for (int t = 2; t <= j; t += 2) {
dp[i-1][j][nk] += dp[i][j][k] * c[j][t] % mod;
dp[i-1][j][nk] %= mod;
}
// add new 1 in old vectors odd
if (!(k == 1 && (K >> (i - 1)) % 2 == 0)) {
int nk = (k == 1 && (K >> (i - 1)) % 2 == 1) ? 1 : 0;
for (int t = 1; t <= j; t += 2) {
dp[i-1][j][nk] += dp[i][j][k] * c[j][t] % mod;
dp[i-1][j][nk] %= mod;
}
}
// be zero
nk = (k == 1 && (K >> (i - 1)) % 2 == 0) ? 1 : 0;
dp[i-1][j][nk] += dp[i][j][k];
dp[i-1][j][nk] %= mod;
}
}
}
LL ans = 0;
REP(j, 31) REP(k, 2)
ans = (ans + dp[0][j][k]) % mod;
cout << ans << endl;
return 0;
}