【百度之星】题目练手

BD202301公园

码题集OJ-公园 (matiji.net)

看到之后就想到之前没写出来的一道cf题目,因为不敢打暴力导致没写出来hhh~

首先,这个问题贪心必有反例(贪心两个人尽早相遇)

数据范围40000, 直接暴力枚举两个人在哪个点相遇。因为并不需要知道任意两个点之间的距离,而是只需要知道t到任意一点的距离,f到任意一点的距离和t到任意一点的距离,三次bfs即可。枚举点求最小值即可。

#include<bits/stdc++.h>

using ll=long long;
using ull=unsigned long long;

using ari=std::array<int,2>;
using PII=std::pair<int,int>;

const int N=4e4+10;
const int mode=1e9+7;
const double eps=1e-6;


int te,fe,s;//小度移动消耗值,度度熊移动消耗值,一起移动的消耗减少值
int t,f,n,m;//小度出发点,度度熊出发点,目标节点,总路径数

std::vector<int> g[N];
int dist[3][N];

void bfs(int x,int tag)
{
    memset(dist[tag],0x3f,sizeof dist[tag]);
    std::queue<int> q;
    dist[tag][x]=0;
    q.push(x);

    while(q.size())
    {
        auto t=q.front();
        q.pop();

        for(auto i:g[t])
        {
            if(dist[tag][t]+1<dist[tag][i])
            {
                dist[tag][i]=dist[tag][t]+1;
                q.push(i);
            }
        }
    }
}
void solve()
{
    std::cin>>te>>fe>>s;
    std::cin>>t>>f>>n>>m;

    for(int i=1;i<=m;i++)
    {
        int x,y;
        std::cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }

    bfs(t,0);
    bfs(f,1);
    bfs(n,2);


    ll ans=1e18;
    for(int i=1;i<=n;i++)
    {
        //std::cout<<dist[0][i]<<'\n';
        //这个点作为集合点
        if(dist[0][i]>=1e9||dist[1][i]>=1e9||dist[2][i]>=1e9) continue;
        ll now=dist[0][i]*te+dist[1][i]*fe+dist[2][i]*(te+fe-s);
        ans=std::min(ans,now);
    }
    if(ans>=1e9) std::cout<<"-1\n";
    else std::cout<<ans<<'\n';
}
signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

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

BD202305糖果促销

码题集OJ-糖果促销 (matiji.net)

二分即可,似乎有O1做法。

注意要特判p,k。当p为1时,永动机了属于是,check函数会进入死循环,这时无论需要吃几颗买一颗即可,如果一颗都不吃输出0即可。

#include<bits/stdc++.h>

using ll=long long;
using ull=unsigned long long;

using ari=std::array<int,2>;
using PII=std::pair<int,int>;

const int N=4e4+10;
const int mod=1e9+7;
const double eps=1e-6;
int p,k;
bool check(int x)
{
    ll sum=x;
    ll zhi=x;
    while(x/p)
    {
        int cnt=x/p;
        sum+=cnt;

        x%=p;
        x+=cnt;
    }
    return sum>=k;
}
void solve()
{
    std::cin>>p>>k;

    if(p==1)
    {
        if(k==0) std::cout<<"0\n";
        else std::cout<<"1\n";
        return ;
    }
    int l=0,r=1e9,res=-1;
    while(l<=r)
    {
        int mid=l+r>>1;
        if(check(mid)){
            res=mid;
            r=mid-1;
        }else l=mid+1;
    }
    std::cout<<res<<'\n';
}
signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值