牛客小白月赛73

A.最小的数字

题目:

分析:

简单枚举一下,找到第一个大于等于n的且是3的倍数的数

代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n;
    cin >> n;
    
    bool loop = true;
    
    if (n % 3 == 0)
            loop = false;
    
    while (loop)
    {
        n ++;
        if (n % 3 == 0)
            loop = false;
    }
    
    cout << n;
    
    return 0;
}

B.优美的GCD

题目:

分析:

根据题目条件,用两个质数分别乘以n即可构造出答案。

代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    
    int t;
    cin >> t;
    
    while (t --)
    {
        int n;
        cin >> n;
        
        cout << n * 2 << " " << n * 3 << endl;
    }
    
    return 0;
}

C.优美的序列

题目:


分析:

如果序列中存在相同项,由于下标差值最小是1,所以无解。
如果序列中不存在相同项,不妨对序列从小到大排序,由于两两各不相同,因此任意相邻两项的差的绝对值都至少是1,对任意1 <= i,j <= n都有|ai - aj| >= |i - j|成立

代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 1010;
int a[N];

int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    
    int t;
    cin >> t;
    
    while (t --)
    {
        int n;
        cin >> n;
        
        unordered_map<int, bool> mp;
        unordered_map<int, int> mp2;
        bool check = false;
        
        for (int i = 0; i < n; i ++)
        {
            cin >> a[i];
            
            if (mp[a[i]])
                check = true;
            mp[a[i]] = true;
        }
        
        if (check)
            cout << -1 << endl;
        else
        {
            sort(a, a + n);
            for (int i = 0; i < n; i ++)
                cout << a[i] << " ";
            cout << endl;
        }
        
    }
    
    return 0;
}

D/E Kevin喜欢零

题目:


分析:

hard版本:
x的末尾恰好有k个0,则x = p×10k = p×2k×5k且p与10互质,换句话说,设x中2的因子数位a, 5的因子数位b,当且仅当min(a, b) = k使得x的末尾恰好有k个0。因此,判断一个区间内元素的累乘结果是否恰好有k个0,即看min(区间内因子2的总数,区间内因子5的总数)是否为k,这个查询判断可以用前缀和来做。接着就是枚举有多少个满足此要求的区间。枚举区间我们可以采用固定一个端点然后枚举另一个端点的方式。不妨固定左端点,枚举右端点,由于我们统计的因子数量是非递减的,因此可以二分右端点,设对于因子2的数量等于k的区间是[l2,r2],因子5的数量等于k的区间是[l5,r5],由于右端点的位置要满足所选区间最小值是k,因此右端点的选择范围是[max(l2,l5), max(r2,r5)]。最后统计所有满足条件的区间数量即可。

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 2e5 + 5;
int a[N];
LL s2[N], s5[N];

int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    
    int t;
    cin >> t;
    
    while (t --)
    {
        int n, k;
        cin >> n >> k;
        
        for (int i = 0; i <= n; i ++)
        {
            s2[i] = s5[i] = 0;
        }
        
        for (int i = 1; i <= n; i ++)
        {
            cin >> a[i];
            
            int m = a[i];
            
            while (m % 2 == 0)
            {
                s2[i] ++;
                m /= 2;
            }
            
            m = a[i];
            
            while (m % 5 == 0)
            {
                s5[i] ++;
                m /= 5;
            }
            
            s2[i] += s2[i - 1];
            s5[i] += s5[i - 1];
        }
        
        LL res = 0;
        
        for (int i = 1; i <= n; i ++)
        {
            LL t2 = s2[i - 1] + k, t5 = s5[i - 1] + k;
            int l2 = lower_bound(s2, s2 + n + 1, t2) - s2, r2 = upper_bound(s2, s2 + n + 1, t2) - s2 - 1;
            int l5 = lower_bound(s5, s5 + n + 1, t5) - s5, r5 = upper_bound(s5, s5 + n + 1, t5) - s5 - 1;
            
            int l = max(l2, l5), r = max(r2, r5);
            
            l = max(i, l); // 避免l枚举到i的左边
            if (l == n + 1) // l为n + 1则说明没有满足条件的右端点
                continue;
            
            res += r - l + 1;
        }
        
        cout << res << endl;
    }
    
    return 0;
}

Kevin的哈希构造

题目:


分析:

考虑dp。定义f[i][j][k]为前i个字符中有j个相同项且字符串哈希值为k的方案是否可行。
初始:f[0][0][0] = 1
转移:
①可以考虑用前面的值来推当前:f[i][j][k] |= f[i - 1][j - (s[i] == c)][(k - (c - 'a' + 1) × bi + p) % p]
②也可以考虑用当前的值来推后面的值:f[i + 1][j + (s[i] == c)][(k × b + (c - 'a' + 1)) % p] |= f[i][j][k]
本人选择的是第二种方式。
目标状态: f[n][k][hash]
至于记录方案则可以用一个pre_h数组记录上一个方案的哈希值以及ch数组记录当前方案的选择的字符。

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 55, M = 1010;

bool f[N][N][M];
LL pre_h[N][N][M];
char ch[N][N][M], s[N];

int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    
    int t;
    cin >> t;
    
    while (t --)
    {
        int n, p, k;
        LL b, H = 0;
        cin >> n >> b >> p >> k;
        
        cin >> s + 1;
        
        memset(f, false, sizeof f);
        f[0][0][0] = true;
        
        for (int i = 1; i <= n; i ++)
            H = (H * b + s[i] - 'a' + 1) % p;
        
        for (int i = 0; i <= n; i ++)
        {
            for (int j = 0; j <= min(i, k); j ++)
            {
                for (int l = 0; l < p; l ++)
                {
                    if (f[i][j][l])
                    {
                        for (char c = 'a'; c <= 'z'; c ++)
                        {
                            LL h2 = (l * b + (c - 'a' + 1)) % p;
                            if (s[i + 1] == c)
                            {
                                f[i + 1][j + 1][h2] = true;
                                pre_h[i + 1][j + 1][h2] = l;
                                ch[i + 1][j + 1][h2] = c;
                            }
                            else
                            {
                                f[i + 1][j][h2] = true;
                                pre_h[i + 1][j][h2] = l;
                                ch[i + 1][j][h2] = c;
                            }
                        }
                    }
                }
            }
        }
        
        if (!f[n][k][H])
            cout << -1 << endl;
        else
        {
            string res;
            
            for (int i = n, j = k, h2 = H; i >= 1; i --)
            {
                res += ch[i][j][h2];
                int tmp = h2;
                h2 = pre_h[i][j][h2];
                if (s[i] == ch[i][j][tmp])
                    j --;
            }
            
            reverse(res.begin(), res.end());
            
            cout << res << endl;
        }
    }
    
    return 0;
}

G.MoonLight的冒泡排序难题

题目:


分析:

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 2e5 + 5, mod = 998244353;
LL f[N];

LL qmi(LL m, LL k)
{
    LL res = 1, t = m;
    
    while (k)
    {
        if (k & 1)
            res = res * t % mod;
        t = t * t % mod;
        k >>= 1;
    }
    
    return res;
}

int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    
    for (int i = 1; i <= N; i ++)
    {
        f[i] = (f[i - 1] + (i - 1) * qmi(i, mod - 2)) % mod;
    }
    
    int t;
    cin >> t;
    
    while (t --)
    {
        int n;
        cin >> n;
        
        cout << f[n] << endl;
    }
    
    return 0;
}
posted @ 2023-05-30 16:04  scoxty  阅读(38)  评论(0编辑  收藏  举报