每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

AtCoder Beginner Contest 236(D,E,F)

AtCoder Beginner Contest 236(D,E,F)

D

D

这道题的大意是有2n个数,我们可以让ij配对,且i<j,那么这一对的值就是a[i][j],他会给出所有可能出现的配对的方式的值,求出n对数得到的值的异或值最大的那一个

我之前是想过暴力,因为这个n小于8,但是我的方向错了,我之前认为每一个数都有2n个可以和它配对,但是就以为是2n2n,我就觉得会不会太大了,然后就没有深想了,现在想来真是太蠢了,脑子不太清醒,虽然方向不对,但是这个时间复杂度的预估也太离谱了,简直了

对于每一对,其实我们不用考虑那么多,其实总共就只有n对,所以较小的那一个,那么那个i我们其实可以顺其自然,后面那一个才是我们需要找的,这里可以用回溯的方式找出最合适的

这次确实是我想的太过于粗暴了,我以为每一个数要找一个和这个数匹配的数,我如果暴力的话(在不管大小的情况下)有(n1)n种情况,就觉得这样就会超时

其实如果我们考虑的大小的关系,如果现在此时需要那个较小的数,那么此时还没有用到的最小的那一个一定是那个i,所以我们其实可以确定此时的i,然后再考虑比i大的数作为j,这样处理就会使得时间复杂度降低

#include <iostream>
#include <vector>
using namespace std;
const int maxn=30;
#define int long long 
int g[maxn][maxn];
bool vis[maxn];
int ans,n;
void dfs(int cur,int cnt,int res)
{
    if (cnt==2*n)
    {
        ans=max(res,ans);
        return ;
    }
    if (cnt%2==0)
    {
        for (int i=1;i<=2*n;i++)
        {
            if (vis[i]) continue;
            vis[i]=true;
            dfs(i,cnt+1,res);
            vis[i]=false;
            return ;
        }
    }
    else 
    {
        for (int i=cur+1;i<=2*n;i++)
        {
            if (vis[i]) continue;
            vis[i]=true;
            int u=cur,v=i;
            dfs(i,cnt+1,res^g[u][v]);
            vis[i]=false;
        }
    }
    return ;
}
signed main ()
{
    cin>>n;
    for (int i=1;i<=2*n;i++)
    {
        for (int j=i+1;j<=2*n;j++)
        {
            cin>>g[i][j];
        }
    }
    ans=0;
    vis[1]=true;
    dfs(1,1,0);
    cout<<ans<<'\n';
    system ("pause");
    return 0;
}

E

E

学习

这个题大意是给你n个数,我们可以从这n个数选择一些数,但是对于1<=i<n,对于这里面的每一个i,我们都必须从ii+1的数至少选一个,然后我们需要满足上面条件的若干个数的最大中位数,最大平均值,这两个值的若干个数的选择是相互独立的

我之前想到好多种变化,这是我们自己构造不出来的(我构造不出来)

然后看了一些题解,万万没想到这个竟然可以用二分来写(我都没有想到这方面上)

那么二分的check函数应该怎么写呢

对于平均数,我们可以知道对于目前已经选择的数的和大于等于此时的x

这里我们要怎么选择呢

我们这里还定义了一个二维的f数组,f[i][0]代表着从1i并且我们不会选择ai的情况,f[i][1]代表着从1i并且我们一定选择ai的情况

那么我们就可以选择一下的转移方式

如果我们此时决定ai的选择

如果不选,f[i][0]=f[i1][1],那么它的前一位必须要选择

如果选,f[i][1]=max(f[i1][1],f[i1][0])+a[i],那么它的前一位可选可不选

对于中位数,我们可以知道不比中位数小的数量要小于比中位数小的数多

具体的细节看代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=1e5+10;
#define int long long 
#define eps 1e-6
int a[maxn],n;
bool check1(double x)
{
    vector<vector<double>>f(n+1,vector<double>(2));
    f[0][0]=f[0][1]=0;
    for (int i=1;i<=n;i++)
    {
        f[i][0]=f[i-1][1];
        f[i][1]=max(f[i-1][1],f[i-1][0])+a[i]-x;
    }
    return max(f[n][0],f[n][1])>=0;
}
bool check2(int x)
{
    vector<vector<int>>f(n+1,vector<int>(2));
    for (int i=1;i<=n;i++)
    {
        f[i][0]=f[i-1][1];
        f[i][1]=max(f[i-1][0],f[i-1][1])+(a[i]>=x?1:-1);
    }
    return max(f[n][0],f[n][1])>0;
}
signed main ()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    double l=0,r=1e9;
    double ave=0;
    while (r-l>=eps)
    {
        double mid=(l+r)/2;
        if (check1(mid))
        {
            l=mid;
            ave=mid;
        }
        else r=mid;
    }
    int L=0,R=1e9;
    int midans=0;
    while (L<=R)
    {
        int mid=(L+R)>>1;
        if (check2(mid))
        {
            midans=mid;
            L=mid+1;
        }
        else R=mid-1;
    }
    cout<<ave<<'\n'<<midans<<'\n';
    system ("pause");
    return 0;
}

F

F

学习

这个题大意是有2n1个数,对于12n1个数,我们如果需要从这些数中选择若干个数,让我们可以得到这若干个数的异或值可以变成1,2,3,4,...22n1,如果我们要选择i,那么会消耗ai的价值,然后我们需要如果有若干个数的异或值可以变成12n1的最小价值

这个是线性基的模板题

线性基

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=2e5+10;
#define int long long 
int n,m;
signed main ()
{
    cin>>n;
    m=1<<n;
    vector<pair<int,int>>v;
    for (int i=1;i<m;i++)
    {
        int x;
        cin>>x;
        v.push_back({x,i});
    }
    sort(v.begin(),v.end());
    int ans=0;
    vector<int>t(n+1,0);
    for (auto [val,x]:v)
    {
        for (int i=0;i<n;i++)
        {
            if ((x>>i&1))
            {
                if (!t[i])
                {
                    ans+=val;
                    t[i]=x;
                    break;
                }
                else 
                {
                    x^=t[i];
                }
            }
        }
    }
    cout<<ans<<'\n';
    system ("pause");
    return 0;
}
posted @   righting  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示