1 条题解
-
1
关于本题
我们可以转移一个表示从前堆中取,丢掉了堆在时,值为的方案数
f[i][j][k] = f[i - 1][[j - 1][k ^ ] + f[i - 1][j][k];
有一个很巧妙的想法是:因为对于任意一个正整数, 它和比它自己小的数字异或起来的结果不会超过,由此可以得出:和比小的数字的异或和不会超过2,此我们可以直接对石子排序,这样的时间复杂度就可以减少到。 最后有个小细节要注意一下:当可以被整除时,结果要减去1
Code
#include <iostream> #include <cstring> #include <algorithm> #define int long long using namespace std; const int N = 2e6 + 10,M = 5 * 1e5 + 10,mod = 1e9 + 7; int n,k; int a[M]; int f[10][N];//f[i][j][k]从前i堆中取,丢掉了j堆,xor值为k的方案数 int flags[N],tmp = 1; int maxn = 0; signed main() { //freopen("4.in","r",stdin); cin >> n >> k; for (int i = 1;i <= n;i ++) { cin >> a[i];maxn ^= a[i]; } sort(a + 1,a + n + 1); f[0][0] = 1; for (int i = 1;i <= n;i ++) { for (;tmp <= a[i];tmp <<= 1); for (int j = 0;j < tmp;j ++) flags[j] = (f[k - 1][j ^ a[i]] + f[0][j]) % mod; //DP : bag for (int j = k - 1;j > 0;j --) { for (int h = 0;h < tmp;h ++) { f[j][h] = (f[j - 1][h ^ a[i]] + f[j][h]) % mod; } } for (int j = 0;j < tmp;j ++) f[0][j] = flags[j]; } if (n % k == 0) { cout << (f[0][maxn] - 1 + mod) % mod << endl; return 0; } cout << (f[0][maxn] + mod) % mod << endl; return 0; }
信息
- ID
- 136
- 时间
- 1500ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 7
- 已通过
- 1
- 上传者