牛客练习赛122

牛客周赛 Round 35

小红的字符串切割

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
const int N = 6010;
vector<vector<int>> dp, e, vis;

void solve()
{
    string s;
    cin >> s;
    int n = s.size();
    n /= 2;
    string a = s.substr(0, n);
    string b = s.substr(n);
    cout << a << endl;
    cout << b << endl;
}

int main()
{
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

小红的数组分配

解题思路:

计算每个数出现次数,如果都是偶数,平均分配即可。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
const int N = 6010;
vector<vector<int>> dp, e, vis;

void solve()
{
    int n;
    cin >> n;
    vector<int> a(2 * n + 1);
    map<int, int> cnt;
    for (int i = 1; i <= 2 * n; i++)
    {
        cin >> a[i];
        cnt[a[i]]++;
    }
    for (auto t : cnt)
    {
        if (t.se & 1)
        {
            puts("-1");
            return;
        }
    }
    vector<int> sa, sb;
    for (auto t : cnt)
    {
        int m = t.se / 2;
        for (int i = 1; i <= m; i++)
        {
            sa.push_back(t.fi);
            sb.push_back(t.fi);
        }
    }
    for (auto x : sa)
    {
        cout << x << ' ';
    }
    cout << endl;
    for (auto x : sb)
    {
        cout << x << ' ';
    }
    cout << endl;
}

int main()
{
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

小红关鸡

解题思路:

排序,双指针维护长度小于等于k的区间,不断更新概率最大值即可。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
const int N = 6010;
vector<vector<int>> dp, e, vis;

void solve()
{
    ll n, k;
    cin >> n >> k;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    sort(a.begin() + 1, a.end());
    int l = 1;
    int r = 1;
    double ans = 0;
    while (l <= r && r <= n)
    {
        while (r + 1 <= n && a[r + 1] - a[l] <= k)
        {
            r++;
        }
        ans = max(ans, (r - l + 1.0) / (1.0 * n));
        l++;
        if (l > r && r + 1 <= n)
        {
            r++;
        }
    }
    printf("%.10lf", ans);
}

int main()
{
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

小红的排列构造

解题思路:

大于n的数要改,小于等于n且出现次数大于1的要改。

改成合法范围内,没出现过的数即可。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
const int N = 6010;
vector<vector<int>> dp, e, vis;

void solve()
{
    int n;
    cin >> n;
    vector<int> a(n + 1);
    int ans = 0;
    map<int, int> cnt;
    int cur = 1;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (a[i] > n)
        {
            ans++;
        }
        else if (cnt[a[i]] > 0)
        {
            ans++;
        }
        cnt[a[i]]++;
    }
    cout << ans << endl;
    for (int i = 1; i <= n; i++)
    {
        if ((a[i] <= n && cnt[a[i]] > 1) || (a[i] > n))
        {
            while (cnt[cur] > 0)
            {
                cur++;
            }
            cnt[a[i]]--;
            cout << i << ' ' << cur << endl;
            cnt[cur]++;
        }
    }
}

int main()
{
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

小红的无向图构造

解题思路:

1为根,先构造有根树。最短路距离就是深度。

若最短路距离之间出现断层,即有深度1,3但无深度2,无解。按深度构造有根树,消耗边n1条。

对于剩余的边,我们有两种处理方法:

  • 同深度结点相连。
  • 深度相差为1的两节点相连。

若如此连接完边还有剩余,那么无解。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
const int N = 6010;

void solve()
{
    int n, m;
    cin >> n >> m;
    vector<pii> a(n + 1);
    vector<vector<int>> d(n + 10, vector<int>());
    map<pii, bool> vis;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i].fi;
        a[i].se = i;
        d[a[i].fi].push_back(i);
    }
    if (m < n - 1)
    {
        puts("-1");
        return;
    }
    sort(a.begin() + 1, a.end());
    for (int i = 2; i <= n; i++)
    {
        if (a[i].fi - a[i - 1].fi > 1)
        {
            puts("-1");
            return;
        }
    }
    m -= n - 1;
    ll res = 0;
    for (int i = 1; i <= n; i++)
    {
        ll x = d[i].size();
        if (x > 0)
        {
            res += (x * (x - 1)) / 2;
        }
        ll y = d[i + 1].size();
        if (x > 0 && y > 0)
        {
            res += (x - 1) * y;
        }
    }
    if (m > res)
    {
        puts("-1");
        return;
    }
    vector<pii> ans;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j < (int)d[i].size(); j++)
        {
            ans.emplace_back((pii){d[i - 1][0], d[i][j]});
            vis[{d[i - 1][0], d[i][j]}] = true;
        }
    }
    // for (int i = 2; i <= n; i++)
    // {
    //     ans.emplace_back((pii){a[i].se, d[a[i].fi - 1][0]});
    //     vis[{a[i].se, d[a[i].fi - 1][0]}] = true;
    // }
    for (int i = 0; i <= n; i++)
    {
        if (m == 0)
        {
            break;
        }
        for (int j = 0; j <= (int)d[i].size() - 1; j++)
        {
            for (int k = j + 1; k <= (int)d[i].size() - 1; k++)
            {
                if (vis[{d[i][j], d[i][k]}] == false)
                {
                    vis[{d[i][j], d[i][k]}] = true;
                    ans.push_back({d[i][j], d[i][k]});
                    m--;
                    if (m == 0)
                    {
                        break;
                    }
                }
            }
            if (m == 0)
            {
                break;
            }
        }
        if (m == 0)
        {
            break;
        }
    }
    for (int i = 0; i <= n; i++)
    {
        if (m == 0)
        {
            break;
        }
        for (int j = 0; j <= (int)d[i].size() - 1; j++)
        {
            for (int k = 0; k <= (int)d[i + 1].size() - 1; k++)
            {
                if (vis[{d[i][j], d[i + 1][k]}] == false)
                {
                    vis[{d[i][j], d[i + 1][k]}] = true;
                    ans.push_back({d[i][j], d[i + 1][k]});
                    m--;
                    if (m == 0)
                    {
                        break;
                    }
                }
            }
            if (m == 0)
            {
                break;
            }
        }
        if (m == 0)
        {
            break;
        }
    }
    if (m > 0)
    {
        puts("-1");
        return;
    }
    for (auto t : ans)
    {
        cout << t.fi << ' ' << t.se << endl;
    }
    cout << endl;
}

int main()
{
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

小红的子序列权值和(easy)

小红的子序列权值和(hard)

解题思路:

一个数的因子个数取决于他质因数分解后,质因子的次数。x=p1α1p2α2。那么x的因子个数为(α1+1)×(α2+1)

本题中只有两个质因子(2,3),所以关键就是维护他们次数之和。

dp[i]:idp[i]

考虑前i个数字,他们序列构成的每个子序列,设子序列中元素乘积为xi

xi=2αi3βi

s[2]=(αi+1)

s[3]=(βi+1)

考虑dp[i]时,首先,相比dp[i1],会多出2i1个子序列。这些子序列中有一个是a[i],其余2i11个子序列为dp[i1]中的所有子序列分别乘以a[i]

  • a[i]=1:那么前面所有的αiβi都不会发生变化,只是单纯子序列的增加。

    • dp[i]=2dp[i1]+1,其中+1是因为a[i]=1,a[i]
    • s[2]=2s[2]+1,对应上面解释。s[3]同理。
  • a[i]=2:前面2i1个子序列要乘以a[i]αi+1

    • dp[i]=2dp[i1]+s[3]+2。其中,+s[3]是因为质因子2的次数+1,参照最初给的根据质因子次数求因子个数的公式。+1是因为a[i]=2,a[i]2

    • s[2]=2s[2]+2i1,s[3]=2s[3]+1

  • a[i]=3:前面2i1个子序列要乘以a[i]βi+1

    • dp[i]=2dp[i1]+s[2]+2。其中,+s[2]是因为质因子3的次数+1,参照最初给的根据质因子次数求因子个数的公式。+1是因为a[i]=3,a[i]2

    • s[3]=2s[3]+2i1,s[2]=2s[2]+1

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
typedef double db;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const int mod = 1e9 + 7;

ll qmi(ll a, ll b)
{
    ll res = 1;
    while (b)
    {
        if (b & 1)
        {
            res = res * a % mod;
        }
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}

void solve()
{
    int n;
    cin >> n;
    vector<ll> a(n + 1);
    vector<ll> cnt(4, 0), s(4, 0);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    vector<ll> dp(n + 1);
    ll ans = 0;
    for (int i = 1; i <= n; i++)
    {
        if (a[i] == 1)
        {
            dp[i] = ((dp[i - 1] * 2) + 1) % mod;
            s[3] = (2 * s[3] + 1) % mod;
            s[2] = (2 * s[2] + 1) % mod;
        }
        else if (a[i] == 2)
        {
            dp[i] = (2 * dp[i - 1] + s[3] + 2) % mod;
            dp[i] %= mod;
            s[3] = (2 * s[3] + 1) % mod;
            s[2] = ((2 * s[2] + 1) + (qmi(2, i - 1))) % mod;
            // cnt[2]++;
            // s[2] = s[2] + (qmi(2, i - 1) * s[3]) + 2;
            // s[2] %= mod;
        }
        else
        {
            dp[i] = (2 * dp[i - 1] + s[2] + 2) % mod;
            dp[i] %= mod;
            s[2] = (2 * s[2] + 1) % mod;
            s[3] = ((2 * s[3] + 1) + (qmi(2, i - 1))) % mod;
            // cnt[3]++;
            // s[3] = s[3] + (qmi(2, i - 1) - 1) + 3;
            // s[3] %= mod;
        }
        // cout << i << ' ' << s[2] << ' ' << s[3] << ' ' << dp[i] << endl;
    }
    cout << dp[n] << endl;
}

int main()
{
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
posted @   value0  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示