Description
一个集合S满足
所有集合元素小于等于n的集合个数。
Solution
可以从线性基考虑。
按数位从高到低加入。
设dpi,j表示考虑前i个
若要加入这个
然后枚举异或和转移就好啦。
#include <bits/stdc++.h>
using namespace std;
const int N = 100;
const int MOD = 1000000007;
typedef long long ll;
int n, m, ans;
int dp[N][N][2];
inline void Add(int &x, int a) {
x += a; while (x >= MOD) x -= MOD;
}
int main(void) {
freopen("1.in", "r", stdin);
cin >> n;
dp[32][0][1] = 1;
for (int i = 32; i; i--)
for (int j = 0; j <= 32; j++) {
Add(dp[i - 1][j][0], (1ll << j) * dp[i][j][0] % MOD);
Add(dp[i - 1][j + 1][0], dp[i][j][0]);
long long t0 = j ? (1 << (j - 1)) : 1,
t1 = j ? (1 << (j - 1)) : 0;
if ((n >> (i - 1)) & 1) {
Add(dp[i - 1][j][1], t1 * dp[i][j][1] % MOD);
Add(dp[i - 1][j][0], t0 * dp[i][j][1] % MOD);
Add(dp[i - 1][j + 1][1], dp[i][j][1]);
} else Add(dp[i - 1][j][1], t0 * dp[i][j][1] % MOD);
}
for (int i = 0; i <= 32; i++) {
Add(ans, dp[0][i][1]);
Add(ans, dp[0][i][0]);
}
cout << ans << endl;
return 0;
}