A. Divan and a Store
题目概述:
K
K
K 元,买价值在
[
l
,
r
]
[l,r]
[l,r]之间的物品,最多买几个。
思路:
从小到大排序后挨着买就好
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 110;
ll a[N];
ll n, l, r, k;
ll cnt;
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --) {
cin >> n >> l >> r >> k;
cnt = 0;
for(int i = 1; i <= n; i ++) cin >> a[i];
sort(a + 1, a + n + 1);
for(int i = 1; i <= n; i ++) {
if(a[i] < l || a[i] > r) continue;
k -= a[i];
if(k < 0) break;
cnt ++;
}
cout << cnt << '\n';
}
}
B. Divan and a New Project
题目概述:
若令
x
0
=
0
x_0 = 0
x0=0 题目转化为
一个长度为
n
n
n 的数组
a
a
a ,现在要求找到一个长度为
n
n
n 的
b
b
b 数组使得
∑
i
=
1
n
∣
a
[
i
]
∗
b
[
i
]
∣
\sum_{i = 1}^{n}|a[i] * b[i]|
∑i=1n∣a[i]∗b[i]∣最小。
思路:
将
a
a
a 排序后, 按照从大到小的顺序依次排放在
x
0
x_0
x0 的两边即可。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
int n;
struct Node {
ll num, pos;
bool operator < (const Node &W) const {
return num > W.num;
}
}a[N];
void solve() {
cin >> n;
int ans[n + 1];
int b[n + 1];
for(int i = 1; i <= n; i ++) {
cin >> a[i].num;
b[i] = a[i].num;
a[i].pos = i;
}
sort(a + 1, a + n + 1);
int x = 1;
ans[0] = n;
//按照(1,-1,2,-2.....) 来放
for(int i = 1; i <= n; i ++) {
if(i % 2) {
ans[a[i].pos] = n + x;
} else {
ans[a[i].pos] = n - x;
x ++;
}
}
ll cnt = 0;
for(int i = 1; i <= n; i ++) {
cnt = cnt + abs(ans[i] - n) * b[i];
}
cout << cnt * 2 << '\n';
for(int i = 0; i <= n; i ++) cout << ans[i] << ' ';
cout << '\n';
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --) {
solve();
}
}
C. Divan and bitwise operations
题目概述:
给出数个
l
,
r
,
x
l, r, x
l,r,x 表示 数组
a
a
a 中
a
l
∣
a
l
+
1
.
.
.
∣
a
r
=
x
a_l | a_{l+1} ...|a_r = x
al∣al+1...∣ar=x
a
a
a 中的每个数都会被包括在其中,现在要求出
a
a
a 的所有子集的异或之和。
思路:
数组
a
a
a 的子集数量为
2
n
2^n
2n 个,当某个区间异或值中的某一二进制位为
1
1
1 时,则对于这个区间来说,如果一定选择该位为
1
1
1 的数,子集数量会变为
2
n
−
1
2^{n-1}
2n−1。 所以一定包含
2
n
−
1
2^{n - 1}
2n−1 个子集的异或值有该位为1的数。
综上,我们对于整个
a
a
a 数组来说,选择区间为整个数组,我们求得所有数的异或值
a
n
s
ans
ans, 最终的答案就是
a
n
s
∗
2
n
−
1
ans * 2^{n-1}
ans∗2n−1。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
ll qmi(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --) {
int n, m;
cin >> n >> m;
ll x;
ll ans = 0;
while(m --) {
cin >> x >> x >> x;
ans |= x;
}
cout << ans * qmi(2, n - 1) % mod << '\n';
}
}
D1. Divan and Kostomuksha (easy version)
题目概述:
通过重新排序
a
a
a 求
∑
i
=
1
n
g
c
d
(
a
1
,
a
2
,
.
.
.
a
i
)
\sum_{i=1}^ngcd(a_1,a_2,...a_i)
∑i=1ngcd(a1,a2,...ai) 的最大值
思路:
d
p
[
x
]
dp[x]
dp[x] 表示以
g
c
d
=
x
gcd = x
gcd=x 开始,能得到的最大值。
- 要得到连续的 g c d ( ) gcd() gcd() 最大,则我们可以将 x x x 的倍数添加进这个序列中,所得到的值为 x x x
- 在添加完 x x x 的倍数后,添加其他数 z z z 时,此时的 g c d gcd gcd 变为了 y y y。
- 那么 d p [ x ] = d p [ y ] + ( x − y ) ∗ c n t [ x ] dp[x] = dp[y] + (x - y) * cnt[x] dp[x]=dp[y]+(x−y)∗cnt[x] ( c n t [ x ] cnt[x] cnt[x] 表示 d p [ x ] dp[x] dp[x] 中 g c d = x gcd = x gcd=x 的元素数量) 这是添加完 z z z 后,使得 g c d = x gcd = x gcd=x 中的所有贡献减少了 x − y x - y x−y
所以状态转移方程为:
d
p
[
x
]
=
m
a
x
(
d
p
[
y
]
+
(
x
−
y
)
∗
c
n
t
[
x
]
)
dp[x] = max(dp[y] + (x - y) * cnt[x])
dp[x]=max(dp[y]+(x−y)∗cnt[x])
初始状态
d
p
[
1
]
=
n
dp[1] = n
dp[1]=n 表示
g
c
d
=
1
gcd = 1
gcd=1 时的和
代码:
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 5e6 + 10;
ll a[N], cnt[N], dp[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int n;
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
cnt[a[i]] ++;
}
for(int i = 1; i <= N; i ++)
for(int j = i * 2; j <= N; j += i)
cnt[i] += cnt[j];
dp[1] = n; //gcd == 1时 和为 n
for(int i = 1; i <= N; i ++)
for(int j = i * 2; j <= N; j += i) {
dp[j] = max(dp[j], dp[i] + (j - i) * cnt[j]);
}
cout << *max_element(dp + 1, dp + 1 + N) << endl;
return 0;
}