(部分)河南萌新联赛2024第(三)场:河南大学

目录

A-圆周率日挑战

B-正则表达式

C-Circle

D-开心消消乐(Right Version)

F-累加器

G-求值

I-游戏

J-keillempkill学姐の卷积

K-暴食之史莱姆

L-SSH


A-圆周率日挑战

思路:上py吧,感觉这是py最有用的一集

import decimal

pi = decimal.Decimal("3.1415926535897932384626433832795028841971")
ans, res, d = 0, 0, 4

for i in range(int(input())):
    p, a = map(int, input().split())
    var = abs(decimal.Decimal(decimal.Decimal(p) / decimal.Decimal(a)) - pi)
    if var == d:
        if p < ans:
            ans, res = p, a
    elif var < d:
        d = var
        ans, res = p, a

print(ans, res)

B-正则表达式

思路:按题意模拟即可

void solve()
{
    int n;
    std::cin>>n;
    i64 res=0;
    while (n--)
    {
        bool f=0;
        std::string s;
        std::cin>>s;
        int tmp=0;

        for(auto &x:s)
        {
            if(x=='.')
            {
                if(tmp<0||tmp>255) f=1;
                tmp=0;
                continue;
            }
            tmp=tmp*10+x-'0';
        }
        if(tmp<0||tmp>255) f=1;
        if(!f) res++;
    }

    std::cout<<res<<'\n';
}

C-Circle

思路:找规律

f\left ( n\right )=\begin{cases} 1,& n=0\\ n^2-n+2,& n\ne 0 \end{cases}

void solve()
{
    int n;
    std::cin>>n;
    for(int i=0;i<n;i++)
    {
        int x;
        std::cin>>x;
        std::cout<<(x==0?1:(i64)x*x-x+2)<<" \n"[i==n-1];
    }
}

D-开心消消乐(Right Version)

思路:O(n)扫一遍即可

void solve()
{
    int n;
    std::cin>>n;
    int cmp=-1,res=0;

    for(int i=0;i<n;i++)
    {
        int x;
        std::cin>>x;
        if(x!=cmp)
        {
            cmp=x;
            if(x) res++;
        }
    }

    std::cout<<res<<'\n';
    
}

F-累加器

思路:观察二进制位的变化,算一下0~x和0~x+y的次数作差即可

void solve()
{
    int x,y;
    std::cin>>x>>y;

    int c=x+y;
    i64 res1=0,res2=0;

    while (x)
    {
        res1+=x/2;
        x/=2;
    }

    while (c)
    {
        res2+=c/2;
        c/=2;
    }

    std::cout<<res2-res1+y<<'\n';

}

G-求值

思路:枚举x,三分y,每次更新最小值

void solve()
{
    i64 a,b,c,n,w;
    std::cin>>a>>b>>c>>n>>w;

    auto check=[&](i64 mid,i64 x)->i64
    {
        return std::abs(a*x+b*mid+(n-mid-x)*c-w);
    };

    i64 res=1e18;

    for(int i=0;i<=n;i++)
    {
        i64 l=0,r=n-i;
        while (l<=r)
        {
            i64 m1=l+(r-l)/3;
            i64 m2=r-(r-l)/3;
            res=std::min({res,check(m1,i),check(m2,i)});
            if(check(m1,i)>check(m2,i))
                l=m1+1;
            else 
                r=m2-1;
        }
    }

    std::cout<<res<<'\n';
    
}

I-游戏

思路:

结果为两种情况:

1.不使用钥匙到n的花费

2.到k之前无法使用钥匙的花费,之后使用钥匙解锁无法通过的道路到n的花费

跑两次最短路即可

void solve()
{
    int n,m,k;
    std::cin>>n>>m>>k;
    k--;
    std::vector<std::vector<std::array<i64,3>>>adj(n);

    for(int i=0;i<m;i++)
    {
        i64 u,v,w,d;
        std::cin>>u>>v>>w>>d;
        u--,v--;

        adj[u].pb({v,w,d});
        adj[v].pb({u,w,d});
    }

    std::priority_queue<std::pair<i64,i64>,std::vector<std::pair<i64,i64>>,std::greater<>> q;

    std::vector<i64> dis(n,1e18);
    std::vector<bool> vis(n,0);
    dis[0]=0;
    q.push({0,0});

    while(sz(q))
    {
        auto [x,y]=q.top();
        q.pop();
        int u=y;
        if(vis[u]) continue;
        vis[u]=1;
        for(auto [v,w,d]:adj[u])
        {
            if(d)
            {
                dis[v]=std::min(dis[v],dis[u]+w);
                q.push({dis[v],v});
            }
        }
    }

     i64 res=dis[n-1],tmp=dis[k];

    std::fill(dis.begin(), dis.end(),1e18);
    std::fill(vis.begin(), vis.end(),0);

    dis[k]=0;
    q.push({0,k});

    while(sz(q))
    {
        auto [x,y]=q.top();
        q.pop();
        int u=y;
        if(vis[u]) continue;
        vis[u]=1;
        for(auto [v,w,d]:adj[u])
        {
            dis[v]=std::min(dis[v],dis[u]+w);
            q.push({dis[v],v});
        }
    }

    res=std::min(res,tmp+dis[n-1]);

    std::cout<<(res==1e18?-1:res)<<'\n';

}

J-keillempkill学姐の卷积

思路:按题意模拟即可

void solve()
{
    int n,m;
    std::cin>>n>>m;
    std::vector<std::vector<int>>a(n,std::vector<int>(n,0)),b(m,std::vector<int>(m,0));

    for(auto &y:a)
        for(auto &x:y)
            std::cin>>x;

    for(auto &y:b)
        for(auto &x:y)
            std::cin>>x;

    for(int i=0;i+n<=m;i++)
    {
        for(int j=0;j+n<=m;j++)
        {
            int res=0;
            for(int di=0;di<n;di++)
                for(int dj=0;dj<n;dj++)
                    res+=b[i+di][j+dj]*a[di][dj];
            std::cout<<res<<" \n"[j==m-n];
        }
    }
}

K-暴食之史莱姆

思路:贪心的LIS,一个史莱姆能吃掉的最大个数应该为两侧小于它体积的第一个的史莱姆能吃掉的个数 + 1,先固定左侧,用单调栈维护一下该侧比当前史莱姆更小的第一个位置,右侧同理

void solve()
{
    int n;
    std::cin>>n;
    std::vector<int>a(n+1,0);
    for(int i=1;i<=n;i++) std::cin>>a[i];

    std::vector<int>f1(n+1,0),f2(n+1,0);

    std::stack<int>st;

    for(int i=1;i<=n;i++)
    {
        while (sz(st)&&a[st.top()]>a[i]) st.pop();
        if(sz(st)) f1[i]=f1[st.top()]+1;
        st.push(i);
    }

    while (sz(st)) st.pop();

    for(int i=n;i;i--)
    {
        while (sz(st)&&a[st.top()]>a[i]) st.pop();
        if(sz(st)) f2[i]=f2[st.top()]+1;
        st.push(i);
    }

    for(int i=1;i<=n;i++) std::cout<<f1[i]+f2[i]<<" \n"[i==n];

}

L-SSH

思路:读题读半天又挺ex的字符串模拟

void solve()
{
    int n,m,q;
    std::cin>>n>>m>>q;
    std::map<std::string,std::string>mp;
    for(int i=0;i<n;i++)
    {
        std::string pub,pri;
        std::cin>>pub>>pri;
        mp[pri]=pub;
    }

    std::map<std::string,std::map<std::string,std::set<std::string>>>mpp;

    for(int i=0;i<m;i++)
    {
        std::string ip;
        int k;
        std::cin>>ip>>k;
        for(int j=0;j<k;j++)
        {
            std::string user;
            int t;
            std::cin>>user>>t;
            for(int p=0;p<t;p++)
            {
                std::string pub;
                std::cin>>pub;
                mpp[ip][user].insert(pub);
            }
        }
    }

    for(int i=0;i<q;i++)
    {
        std::string name,ip,pri;
        std::cin>>name>>ip>>pri;
        if(mpp[ip][name].count(mp[pri])) std::cout<<"Yes\n";
        else std::cout<<"No\n";
    }

}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值