D - Xor Sum 4
题意:
给定一个序列,求序列中任意两个数的异或和
思路:
按位考虑,第
i
i
i 位的贡献为序列中第
i
i
i 位为
0
0
0 的数的个数
×
\times
× 第
i
i
i 位为
1
1
1 的数的个数
×
\times
×
2
i
2^i
2i
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 2e6 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int a[100];
ll ans = 0;
void work()
{
cin >> n;
for(int i = 1; i <= n; ++i){
ll x;cin >> x;
for(int j = 0; j < 60; ++j) if(x & (1ll << j))
++a[j];
}
ll p = 1;
for(int i = 0; i < 60; ++i){
(ans += a[i] * (n - a[i]) % mod * p % mod) %= mod;
p = p * 2 % mod;
}
cout << ans;
}
int main()
{
ios::sync_with_stdio(0);
// int TT;cin>>TT;while(TT--)
work();
return 0;
}
E - Balanced Path
题意:
给定一个矩阵,每个格子有两个数
a
i
,
j
,
b
i
,
j
a_{i,j}, \ b_{i,j}
ai,j, bi,j,选择一个涂成红色,另一个涂成蓝色。问从
(
1
,
1
)
(1,1)
(1,1) 到
(
n
,
m
)
(n,m)
(n,m) 选择一条路线,使得红色权值之和与蓝色权值之和绝对相差最小.
思路:
类似于砝码称重的背包问题
f
[
i
]
[
j
]
[
w
]
f[i][j][w]
f[i][j][w] 表示走到格子
(
i
,
j
)
(i,j)
(i,j) 的答案最小值
题解,没用bitset优化
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 80 + 1;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
bitset <25601> f[maxn][maxn];
int a[maxn][maxn], b[maxn][maxn];
void work()
{
cin >> n >> m;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
cin >> a[i][j];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
cin >> b[i][j];
f[1][1][12801 - a[1][1] + b[1][1]] = 1;
f[1][1][12801 + a[1][1] - b[1][1]] = 1;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
if(i == 1 && j == 1) continue;
f[i][j] |= f[i-1][j] >> abs(a[i][j] - b[i][j]);
f[i][j] |= f[i-1][j] << abs(a[i][j] - b[i][j]);
f[i][j] |= f[i][j-1] >> abs(a[i][j] - b[i][j]);
f[i][j] |= f[i][j-1] << abs(a[i][j] - b[i][j]);
}
int ans = f[n][m].count();
for(int i = 0; i <= 12800; ++i)
if(f[n][m][12801 - i] || f[n][m][12801 + i]){
ans = i;break;
}
cout << ans;
}
int main()
{
ios::sync_with_stdio(0);
// int TT;cin>>TT;while(TT--)
work();
return 0;
}