Codeforces Round 948 (Div. 2)题解

A.Little Nikita

题意:

\(n\)步操作,\(+1\)\(-1\),最终结果是否等于\(m\)

思路:

\(+1\)的操作次数为\(x\),\(-1\)的操作次数为\(y\)

\[x+y=n \\ x-y=m \]

\[x=(n+m)/2 \\ y=(n-m)/2 \]

\((n-m)\)\((n+m)\)均为偶数,即\(n\)\(m\)均为偶数或同为奇数,且\(n>=m\)

代码:

void solve()
{
    int n, m;
    cin >> n >> m;
    if (((n & 1) == (m & 1)) && n >= m)
    {
        cout << "Yes" << endl;
    }
    else
    {
        cout << "No" << endl;
    }
}

B. Binary Colouring

题意:

构造题。给定一个\(x\),使用一个包含\(-1,0,1\)的数组按照二进制的方式表示\(x\),且数组中不能连续出现不为零的情况

思路:

考虑 \([a_{l},a_{r}]\) 全为\(1\)时,等价为 $a_{l}=-1,a_{r+1}=1,\forall x \in [a_{l+1},a_{r}]=0 $

通过上述方式构造,可能会出现相邻位置同时不为零的情况,讨论\(a_{i},a_{i+1}\)

\(a_{i}=-1,a_{i+1}=1\),等价为 \(a_{i}=1,a_{i+1}=0\)

\(a_{i}=1,a_{i+1}=-1\),等价为 \(a_{i}=-1,a_{i+1}=0\)

代码:


const int N = 32;
int a[N], ans[N];
void solve()
{
    int x;
    cin >> x;
    for (int i = 0; i <= 31; i++)
    {
        a[i] = 0;
        ans[i] = 0;
        a[i] = (x >> i) & 1;
    }
    for (int i = 0; i <= 31; i++)
    {
        if (a[i] == 1)
        {
            int len = 0;
            while (i <= 31 && a[i] == 1)
            {
                len++;
                i++;
            }
            ans[i] = 1;
            ans[i - len] = -1;
        }
    }
    for (int i = 0; i <= 30; i++)
    {
        if (ans[i] == -1 && ans[i + 1] == 1)
        {
            ans[i] = 1, ans[i + 1] = 0;
        }
        if (ans[i] == 1 && ans[i + 1] == -1)
        {
            ans[i] = -1, ans[i + 1] = 0;
        }
    }
    cout << 32 << endl;
    for (int i = 0; i <= 31; i++)
    {
        cout << ans[i] << " ";
    }
    cout << endl;
}

C.Nikita and LCM

题意:

给定一个数组\(A\),找出一个最长的子数组,使其子数组的最小公倍数未在原数组中出现过

思路:

\(mx=MAX(a_1,a_2,...,a_{n})\),考虑两种情况,通过枚举\(a_{i}\)

  • 存在 $ a_{i} \nmid mx$ 的情况,此时\(LCM(mx,a_{i})>mx\),即有\(LCM(a_1,a_2,...,a_{n})> a_n\)

    此时答案为\(n\)

  • 不存在$ a_{i} \nmid mx$ 的情况,即任意\(a_{i}\)都是\(mx\)的因数

    对任意子数组\(a_{p1},a_{p2},...,a_{pm}\)进行\(LCM\)运算都是\(mx\)的因数

    考虑枚举\(mx\)的因数\(t\)

    $t \notin A $并且存在 \(a_{p1},a_{p2},...,a_{pm}\)使得 \(LCM(a_{p1},a_{p2},...,a_{pm})=t\)

    得到一个合法答案\(m\),维护最大值即可

    考虑子数组的选择,因为 \(LCM(a_{p1},a_{p2},...,a_{pm})=t\),则子数组都是\(t\)的因数,只需要在枚举\(a_{i}\)时判断是否整除\(t\)即可

代码

const int N = 2e3 + 5;
ll a[N];
int n, ans = 0;
unordered_map<int, int> mp; // 记录是否出现过

ll lcm(ll a, ll b)
{
    return a / __gcd(a, b) * b;
}

void check(ll t)
{

    int res = 0;
    ll tmp = 1;
    for (int i = 1; i <= n; i++)
    {
        if (t % a[i] == 0)
        {
            tmp = lcm(tmp, a[i]);
            res++;
        }
    }
    if (tmp == t)
    {
        ans = max(ans, res);
    }
}

void solve()
{
    ans = 0;
    mp.clear();
    cin >> n;
    ll mx = 0;
    ll cnt = 1; // 所有数的lcm
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        mp[a[i]]++;
        mx = max(mx, a[i]);//维护最大值
    }
    for (int i = 1; i <= n; i++)
    {
        if (mx % a[i] != 0)
        {
            cout << n << endl;
            return;
        }
    }
    for (int i = 1; i * i <= mx; i++)
    {
        if (mx % i == 0)
        {
            if (mp[i] == 0)
            {
                check(i);
            }
            if (mp[mx / i] == 0)
            {
                check(mx / i);
            }
        }
    }
    cout << ans << endl;
}
posted @ 2024-05-28 11:18  Gu_diao  阅读(244)  评论(0)    收藏  举报