CF1864C 题解

发布时间 2023-08-30 16:20:59作者: yuhang-ren

CF1864C Divisor Chain 题解

洛谷

Codeforce

Description

给定一个整数 \(x\),目标是在最多 \(10^{3}\) 次操作内把 \(x\) 减到 \(1\)

定义一个操作:选择一个 \(x\) 的因数 \(d\),把 \(x\) 修改为 \(x-d\)

同时还有一个额外的限制:相同的 \(d\) 值不能选择超过 \(2\) 次。

\(t\) 组测试数据。

数据范围:\(1\le t\le 10^3,2\le x\le 10^9\)

Solution

一个很显然的事情是对于一个 \(x = 2^{k}\),我们只需要 \(k\) 次操作就可以了,具体的,每次我们让 \(x\) 变为 \(\frac{x}{2}\),直到 \(x = 1\),这个过程每个数只会用一次。

因此让我们考虑如何让 \(x = 2^{k}\),我们可以保留其二进制下最高位的 \(1\),将其余的全部删除。具体的,我们每次将 \(x\) 消掉二进制下最低位的 \(1\),这个过程可以用 \(\operatorname{lowbit}(x)\) 轻松完成。

Codes

#include <bits/stdc++.h>
using namespace std;
#define int long long
void read(int &p)
{
    p = 0;
    int k = 1;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-')
        {
            k = -1;
        }
        c = getchar();
    }
    while (c >= '0' && c <= '9')
    {
        p = p * 10 + c - '0';
        c = getchar();
    }
    p *= k;
    return;
}
void write_(int x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9)
    {
        write_(x / 10);
    }
    putchar(x % 10 + '0');
}
void writesp(int x)
{
    write_(x);
    putchar(' ');
}
void writeln(int x)
{
    write_(x);
    putchar('\n');
}
int T,n;
int lowbit(int x)
{
    return (-x)&x;
}
vector<int> ans;
void solution()
{
    ans.clear();
    read(n);
    ans.push_back(n);
    int c = 0;
    while(n != lowbit(n))
    {
        ans.push_back(n - lowbit(n));
        n -= lowbit(n);
    }
    while(n > 1)
    {
        ans.push_back(n / 2);
        n /= 2;
    }
    writeln(ans.size());
    for(auto now:ans)
    {
        writesp(now);
    }
    puts("");
}
signed main()
{
    read(T);
    while(T--)
    {
        solution();
    }
    return 0;
}