一个整数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; }