牛客周赛 Round 98 [A-F]
A-小红与奇数
题意
给你一个\(x\)(\(1 \leqslant x \leqslant 10^3\)), 请问\(x\)加上自己的一个因子能否变成奇数
tag:暴力
Code (C++)
void whx()
{
    int n;
    vector a;
    cin >> n;
    for (int i = 1; i <= n / i; i ++ )
    {
        if (n % i == 0)
        {
            if (i != n / i) a.push_back(n / i);
            a.push_back(i);
        }
    }
    for (int i = 0; i < a.size(); i ++ )
    {
        if ((n + a[i]) % 2 != 0)
        {
            cout << "Yes\n";
            return;
        }
    }
    cout << "No\n";
}
 
 思路
暴力,预处理出x的所有因子,然后一个一个试找到奇数输出Yes,找不到输出No
B-小红与gcd三角形
题意
给你\(x\),\(y\),\(gcd(x, y)\),判断能否组成非退化三角形
tag:gcd性质,数学判断三角形。
思路
记\(z=gcd(x, y)\), 然后根据定义判断两边之和大于第三条边,又因为\(gcd(x, y)\)一定 \(\leqslant\) \(x\) 或 \(y\)。所以只要满足\(z + y \leq x\)
Code (C++)
void whx()
{
    cin >> x >> y;
    int z = __gcd(x, y);
    if (x < y) swap(x, y);
    // z, y, x
    if (z + y > x)
    {
        cout << "Yes\n";
    }
    else cout << "No\n";
}
 C-小红与red
题意
给你一个长度为n(\(1 \leqslant n \leqslant 10^3\))的仅由'r','e','d'组成的字符串,可以把任意个字符修改为'r','e','d'。
请你用最少的修改次数构造出一个不存在任何相邻相同字符的字符串。
tag: 分类讨论。
思路
对于每一位是否要更换,以及更换为什么字符要结合前一位和后一位综合考虑。
如果存在相邻相同,更改靠后的字符,并且换成和前后都不同的字符。
Code (C++)
void whx()
{
    cin >> n >> s;
    for (int i = 1; i < n; i ++ )
    {
        if (s[i] == s[i - 1])
        {
            if (i == n - 1)
            {
                if (s[i] == 'r')
                {
                    s[i] = 'e';
                }
                else if (s[i] == 'e')
                {
                    s[i] = 'd';
                }
                else if (s[i] == 'd')
                {
                    s[i] = 'r';
                }
            }
            else
            {
                 if (s[i] == 'r')
                {
                    if (s[i + 1] == 'r' || s[i + 1] == 'e')
                    {
                        s[i] = 'd';
                    }
                    else if (s[i + 1] == 'd')
                    {
                        s[i] = 'e';
                    }
                }
                else if (s[i] == 'e')
                {
                    if (s[i + 1] == 'r' || s[i + 1] == 'e')
                    {
                        s[i] = 'd';
                    }
                    else if (s[i + 1] == 'd')
                    {
                        s[i] = 'r';
                    }
                }
                else if (s[i] == 'd')
                {
                    if (s[i + 1] == 'd' || s[i + 1] == 'e')
                    {
                        s[i] = 'r';
                    }
                    else if (s[i + 1] == 'r')
                    {
                        s[i] = 'e';
                    }
                }
            }
        }
    }
    for (int i = 0; i < n; i ++ )
    {
        cout << s[i];
    }
    cout << "\n";
}
 D-小红与好数组
题意
定义一个[好数组]当且仅当相邻元素不同且元素均为正整数。
现在输入一个正整数n(\(1 \leqslant n \leqslant 20\)),找到所有满足下述条件的数组:
- 数组的所有元素之和等于n
 - 数组是[好数组]
 
按字典序从小到大的顺序依次输出所有满足条件的数组
tag: 暴搜,dfs。
思路
\(n \leq 20\),所以可以暴搜(分配n个数)所有情况,对于每个数给最后一位加1或者在末尾添加一位填上1,直到n次操作所有元素之和都是1,然后筛出满足条件的数组。
复杂度:\(O(2^n*n)\)
Code (C++)
int n;
set> st;
bool check(vector& a)
{
    int sum = 0;
    for (int i = 0; i < a.size(); i ++ )
    {
        sum += a[i];
        if (i)
        {
            if (a[i] == a[i - 1]) return false;
        }
    }
    return sum == n;
}
void dfs(int u, vector& a)
{
    // debug(u);
    if (u > n)
    {
        if (check(a))
        {
            st.insert(a);
        }
        return;
    }
    if (a.size() > 0)
    {
        int v = a.back();
        a[a.size() - 1] = ++ v;
        dfs(u + 1, a);
        a[a.size() - 1] = -- v;
    }
    a.push_back(1);
    dfs(u + 1, a);
    a.pop_back();
}
void whx()
{
    cin >> n;
    vector a;
    dfs(1, a);
    for (auto arr : st)
    {
        for (auto x : arr)
        {
            cout << x << " ";
        }
        cout << "\n";
    }
}
    
 E-小红与gcd和sum
题意
定义一个长度为k的数组a的权值为 \(gcd(a1,a2,...,ak) * Sk\), Sk表示前k项和。
请你从a中挑选出权值最大的非空子序列
tag:埃氏筛思想。
思路
预先开一个权值桶记录每个数的权值,枚举每个约数d[1, ma], 然后根据d来计算sum,只要是d的倍数就会对sum产生贡献,利用埃氏筛的思想枚举所有倍数同时从桶中拿出权值累加起来。
Code (C++)
void whx()
{
    int n;
    vector cnt(1e6 + 10, 0);
    cin >> n;
    int d = 0;
    for (int i = 1, x; i <= n; i ++ )
    {
        cin >> x;
        cnt[x] += x;
        d = max(d, x);
    }
    // for (int i = 1; i <= n; i ++ ) cout << cnt[i] << " \n"[i == n];
    int ans = 0;
    for (int i = 1; i <= d; i ++ )
    {
        int sum = 0;
        for (int j = i; j <= d; j += i)
        {
            sum += cnt[j];
        }
        // debug(i, sum);
        ans = max(ans, sum * i);
    }
    cout << ans << "\n";
}
 
 F-小红与天使猫猫酱
题意
有一个无限长的数组\(a = \{22^2, 22^{22}, 22^{222},...\}\),记下标从 1 开始,相应的b数组中 \(b_i = a_i的因子个数\)。设\(B_i\) 为\(b_i\)的前i项和,给你一个 \(n\),求 \(B_n\)
tag:推式子
思路
\(22^2 = 2^2 * 11^2\) \(因数个数 = (2 + 1) * (2 + 1) = (2 + 1)^2\)
\(=>\) \(22^{k}\) \(因数个数 = (k + 1)^2\)
\(B_n = b_1 + b_2 + ... + b_n\)
\(= (2 + 1) ^ 2 + (22 + 1) ^ 2 + ..。 + (2...2{n个} + 1) ^ 2\)
\(= (2^2 + 22^2 + ... + 2...2^2) + 2*(2 + 22 + ... + 2...2) + n\)
\(= 4*(1^2 + 11^2 + ... + 1...1^2) + 4 * (1 + 11 + ... + 1...1) + n\)
设上式 $ = 4(S_n + T_n) + n$
利用高中数列知识推出来
\(S_n = \frac{10^{n+1} - 10 - 9i}{81}\)
\(T_n = \frac{n + \frac{100^{n + 1} - 100}{99} - 2(10^{n + 1} - 10)}{81}\)
\(B_n = \frac{\frac{400(100^n - 1)}{99} - \frac{280(10^n - 1)}{9} + 49n}{81}\)
题目中要求取模,所以计算除法时要用乘法逆元来处理。
Code (C++)
int n;
int ksm(int a, int b)
{
    int res = 1;
    while (b)
    {
        if (b & 1) res = res * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return res;
}
int inv(int x)
{
    return ksm(x, mod - 2);
}
void whx()
{
    cin >> n;
    int fz, fm, a, b, c;
    fm = 81;
    a = 400 * (ksm(100, n) - 1) % mod * inv(99) % mod;
    b = 280 * (ksm(10, n) - 1) % mod * inv(9) % mod;
    c = 49 * (n % mod) % mod;
    fz = (a + b + c) % mod;
    cout << fz * inv(fm) % mod << "\n";
}
 
                
            
        
浙公网安备 33010602011771号