B. Find The Array
题意:给出序列a,S为a的所有元素之和。要求构造出一个序列b,使b中相邻元素为倍数关系,且b中元素与a中元素差值不能超过S/2.
思路:要求构造倍数关系,那么利用a元素的范围进行构造,构造出从1~\(2^{31}\),用二分选出与\(a_i\)相近的数字,由于每个构造出来的数字与原数字的差值不会超过它自己的一半,所以即使整个数组都改,也不会超过总和的一半。
int a[N];
//注意观察N的大小
void solve() {
int n;
cin >> n;
for (int i = 1; i <= n; i ++) {
int x;
cin >> x;
int pos = upper_bound(a, a + 31, x) - a;
cout << a[pos - 1] << " \n"[i == n];
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
a[0] = 1;
for (int i = 1; i <= 31; i ++) a[i] = 1 << i;
cin >> t;
while (t--) {
solve();
}
return 0;
}
\[\]C. Ping-pong
题意:Alice有x点体力,Bob有y点体力,每次击球消耗一点,问最后两人分别赢了多少场
思路:题目只是问最终会赢多少,没说要最小。所以答案就是x-1,y。每个人赢得自己体力的场次,Alice先击球,所以会被Bob抵消一个。
void solve() {
int x, y;
int resx, resy;
cin >> x >> y;
cout << x - 1 << ' ' << y << endl;
}
\[\]B. Jumps
题意:起点为0,要到达坐标为x的点。每次跳跃可以跳i各单位或者后退一个单位。问最少需要多少次
思路:累加即可,直到和大于等于x,如果正好是x+1,则多走一步:向后退一个单位,否则在1~i次跳跃中,选择一次将其改为向后一格即可
void solve() {
int x;
cin >> x;
int cnt = 0, sum = 0;
for (int i = 1; i <= 1e6; i ++) {
if (sum >= x) {
if (sum - x == 1) cnt ++;
break;
}else sum += i, cnt ++;
}
cout << cnt << endl;
}
\[\]D. Number into Sequence
题意:给出一个数字n,要求将n分解为若干因数,且是前面的因数都可以整除后面的的最长序列
思路:将n的所有因数各自的数量存在map中,然后找到具有最多数量的因数k,输出前k - 1个,然后将最后一个乘入剩余没用到的因数中
void solve() {
LL n, x;
cin >> n;
x = n;
map<LL, LL> mp;
for (LL i = 2; i * i <= n; i ++) {
while (n % i == 0) {
mp[i] ++;
n /= i;
}
}
LL maxv = -INF, tmp;
for (auto i : mp) {
if (i.second > maxv) {
maxv = i.second;
tmp = i.first;
}
}
if (maxv < 0) {
cout << 1 << endl;
cout << n << endl;
return ;
}
x /= pow(tmp, maxv);
cout << maxv << endl;
for (auto i : mp) {
if (i.second == maxv) {
for (int j = 1; j <= i.second - 1; j ++) {
cout << i.first << " ";
}
cout << x * i.first << endl;
break;
}
}
}