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