牛客小白月賽104(A~D)

长皆發表於2024-11-08

比賽連結:https://ac.nowcoder.com/acm/contest/94879#question
牛客還是經典暴力時要求程式碼賊多啊

A.小紅購買裝備

題目描述:

小紅準備去打地下城,在進入地下城之前首先需要購買合適的裝備。
已知商店共有\(n\)件裝備,每種裝備提供\(a_i\)的攻擊和\(b_i\)的防禦,價格為\(c_i\),小紅身上已有的裝備攻擊為\(x\),防禦為\(y\),該裝備賣給商店可以回收\(z\)金幣。另外小紅擁有的金幣數量為\(T\)
小紅的戰鬥力計算為攻擊+防禦。現在小紅想知道自己最終從裝備處可以獲得的戰鬥力最大值是多少?
注:小紅最多隻能生效一件裝備!

輸入描述:
第一行輸入五個正整數\(n, x, y, z, T\),分別代表商店的裝備數量、小紅身上的裝備攻擊、防禦、回收價格,以及小紅攜帶的金幣。
接下來的\(n\)行,每行輸入三個正整數,代表商店每件裝備的攻擊、防禦和金幣數量。
\(1 ≤ n ≤ 10^5\)
\(1 ≤ x, y, z, a_i, b_i, c_i, T ≤ 10^9\)

輸出描述:
一個正整數,代表小紅從裝備處獲得的最高戰鬥力。

輸入:
2 100 30 50 100
120 50 120
200 100 1000
輸出:
170
思路:小紅最多隻能生效一件裝備!注意這句話,所以要麼就是不換裝備,要麼就是把裝備買掉,用總金額去買更好的

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long
#define lowbit(x) (x & -x)
//#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
    fio();
    ll n,x,y,z,t;
    cin>>n>>x>>y>>z>>t;
    ll ans=x+y;
    ll op=x+y;
    ll u=z+t;
    for(ll i=1;i<=n;i++)
    {
        ll x,y,z;
        cin>>x>>y>>z;
        if(z<=u)
        {
            ans=max(ans,x+y);
        }
    }
    cout<<ans<<endl;
}

B.小紅招募英雄

小紅將裝備整備完畢,準備招募共同冒險的英雄。
已知英雄共有5種稀有度:N、R、SR、SSR、UR。小紅每次招募將優先選擇稀有度為SSR和UR的英雄。小紅一共需要2名隊友,現在給出每次招募出每個稀有度的機率,請你幫小紅計算單次十連抽(等同於抽取10次)即可湊齊隊友(即不小於2名SSR以上稀有度英雄)的機率。

輸入描述:

五個小數p1, p2, p3, p4, p5,分別代表單次抽取時,N、R、SR、SSR、UR被抽到的機率。
\(0 ≤ p1, p2, p3, p4, p5 ≤ 1\)
\(p1 + p2 + p3 + p4 + p5 = 1\)

輸出描述:
一個小數,代表小紅單次十連抽即可湊齊兩名隊友的機率。如果相對誤差或絕對誤差不超過 \(10^-6\),您的答案將被接受。具體來說,設您的答案為 a,裁判的答案為 b,當且僅當 \(|a-b| ≤ max(1,|b|) * 10^{-6}\) 時,您的答案將被接受。

輸入:
0.2 0.2 0.2 0.2 0.2
輸出:
0.9536425984
思路:經典容斥,直接考慮不行的事件,即9次沒有SSR和UR,和10次沒有SSR和UR,最後用1減去這個機率

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long
#define lowbit(x) (x & -x)
//#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
    fio();
    double a[50];
    double ans=0;
    double u=0;
    for(ll i=1;i<=5;i++)
    {
        cin>>a[i];
        if(i<=3)
        {
            u+=a[i];
        }
    }
    double cnt=1;
    for(ll i=1;i<=10;i++)
    {
        cnt*=u;
        if(i==9)
        {
            ans+=cnt*(a[4]+a[5])*10;
        }
        else if(i==10)
        ans+=cnt;
    }
    ans=1-ans;
    printf("%.10lf\n",ans);
}

C.小紅打怪

有n個怪物排成一排,小紅和隊友們準備進攻這些怪物。
小紅的技能是全體打擊,對所有怪物造成1點傷害。
隊友1的技能是單體打擊,對單體怪物造成1點傷害。
隊友2的技能是範圍攻擊,對相鄰的兩隻怪物分別造成1點傷害(可以對死去的怪物屍體釋放該技能)。
每回合每個人均可釋放1次技能。小紅想知道,擊殺全部怪物最少需要多少回合?

輸入描述:
第一行輸入一個正整數n,代表怪物的總數。
第二行輸入n個正整數\(a_i\),代表每個怪物的血量。
\(2 ≤ n ≤ 10^5\)
\(1 ≤ a_i ≤ 10^9\)

輸出描述:
一個整數,代表擊殺全部怪物的最少回合數。
輸入:
5
1 2 3 4 5
輸出:
2
思路:典型二分問題,這裡用了優先佇列,仔細想想其實直接遍歷也行(自己搞複雜了)。直接二分可能的回合數,然後首先大家都減去回合數,剩下的數用優先佇列開pair<ll,ll>,存數值和下標,每次詢問頭時,問下左邊和右邊有沒有大於0的存在,有就進行第三種操作,無則進行第二種操作,如果不能進行第二種就進行第三種,否則反之,每次操作開始前記得比較下現在的頭是否時正確的,否則彈出。最後如果兩種操作都沒有了,且佇列還大於0,則返回0,否則返回1

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[450000];
ll n;
ll b[450000];
ll ck(ll mid)
{
    priority_queue<pair<ll,ll>>q;
    for(ll i=1;i<=n;i++)
    {
        b[i]=a[i];
        b[i]-=mid;
        if(b[i]>0)
        {
        q.push({b[i],i});
        }
    }
    b[n+1]=b[0]=0;
    ll pd=1;
    ll ans,cnt;
    ans=cnt=mid;
    while(!q.empty())
    {
        if(b[q.top().second]!=q.top().first)
        {
            q.pop();
            continue;
        }
        if(q.top().first==0)
        {
            break;
        }
       if(ans==0&&cnt==0)
       {
        pd=0;
        break;
       }
        if(ans>0)
       {
        ll x=q.top().first;
        ll y=q.top().second;
        q.pop();
        ll z=ans;
        if(b[y+1]>0)
        {
            z=min({z,b[y+1],b[y]});
            b[y+1]-=z;
            b[y]-=z;
            ans-=z;
            q.push({b[y+1],y+1});
            q.push({b[y],y});
        }
        else if(b[y-1]>0)
        {
            z=min({z,b[y-1],b[y]});
            b[y-1]-=z;
            b[y]-=z;
            ans-=z;
            q.push({b[y-1],y-1});
            q.push({b[y],y});
        }
        else 
        {
            z=cnt;
             if(cnt>0)
             {
               z=min({z,b[y]});
               b[y]-=z;
               cnt-=z;
               q.push({b[y],y}); 
             }  
             else 
             {
                z=ans;
                z=min(z,b[y]);
                b[y]-=z;
                ans-=z;
                q.push({b[y],y});
             }
           
        }
       }
        else if(cnt>0)
       {
        ll x=q.top().first;
        ll y=q.top().second;
        q.pop();
        ll z=cnt;
        z=min(z,b[y]);
        b[y]-=z;
        cnt-=z;
        q.push({b[y],y});
       }
    }
    return pd;
}
int main()
{
    fio();
    cin>>n;
    ll sum=0;
    for(ll i=1;i<=n;i++)cin>>a[i],sum+=a[i];
    ll l=1,r=(ll)1e9+5;
    while(l<r)
    {
        ll mid=(l+r)>>1;
        if(mid*n+mid+mid*2<sum)
        {
            l=mid+1;
            continue;
        }
        if(ck(mid))
        {
            r=mid;
        }
        else 
        l=mid+1;
    }
   cout<<r<<endl;
}

D.小紅開鎖

小紅來到了地下城的門口,發現門口有一個密碼鎖。
這個鎖一共有n層,每層為一個正方形的圖案。小紅每次操作一次可以選擇一層使其每個位置的元素按順時針移動一個格子。
該圖演示一個3層的鎖,小紅操作第二層時的變化。

該鎖以中心為原點建立平面直角座標系後,每個象限為一個區域,共分為4個區域,當且僅當某個區域內全部為'X'圖案、且其餘三個區域全部為'O'圖案時,鎖被解開。
小紅想知道,這個鎖需要操作最少多少次可以解開?

輸入描述:
第一行輸入一個正整數n,代表鎖的層數。
接下來輸入2n行,每行輸入一個長度為2n的字串,用來表示鎖的初始圖案。
1 ≤ n ≤ 100
保證存在一個合法的開鎖方式。

輸出描述:
一個整數,代表小紅需要操作的最少次數。
輸入:
2
OXXX
OOOO
OXOO
OOOO
輸出:
3
思路:暴力就行了,討論四個角,這裡給出一個最佳化暴力的方法,從左上角順時針一個圈標記一個位置如1 2 3 等等,最終長度可以根據邊長來進行計算。然後每次也是從左上角走一個順時針圈,遇到X標記一下,如果X斷開就說明現在是X段的頭,然後討論下它的位置和我要去的標記點的位置就可以了,這裡寫個函式,十分方便四個後續三個角討論(這四個標記位置可由觀察規律得出),最終四個方案下取個最優的就行了。具體推薦看看程式碼

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long
#define lowbit(x) (x & -x)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
string f[25000];
ll ck(ll v,ll l,ll r,ll z,ll y,ll cd)
{
    ll pd=0;
    ll wz=0;
    for(ll i=z;i<=y;i++)
    {
        if(pd==-1)
        break;
        if(pd==0)
        {
        wz++;
        if(f[l][i]=='X')
        pd=1;
        }
        else 
        {
            wz++;
            if(f[l][i]=='O')
            {
                wz--;
                pd=-1;
                break;
            }
        }
    }
    for(ll i=l+1;i<=r;i++)
    {
        
        if(pd==-1)
        break;
        if(pd==0)
        {
        wz++; 
        if(f[i][y]=='X')
        pd=1;
        }
        else 
        {
            wz++;
            if(f[i][y]=='O')
            {
                wz--;
                pd=-1;
                break;
            }
        }
    }
    for(ll i=y-1;i>=z;i--)
    {
          if(pd==-1)
        break;
        if(pd==0)
        {
        wz++;
        if( f[r][i]=='X')
        pd=1;
        }
        else 
        {
            wz++;
            if(f[r][i]=='O')
            {
                wz--;
                pd=-1;
                break;
            }
        }
    }
    for(ll i=r-1;i>=l+1;i--)
    {
          if(pd==-1)
        break;
        if(pd==0)
        {
        wz++;
        if(f[i][z]=='X')
        pd=1;
        }
        else 
        {
            wz++;
            if(f[i][z]=='O')
            {
                wz--;
                pd=-1;
                break;
            }
        }
    }
    if(wz<=v)
    {
        return v-wz;
    }
    else 
    {
        return cd-wz+v;
    }

}
int main()
{
    fio();
    ll n;
    cin>>n;
    for(ll i=1;i<=2*n;i++)
    {
        cin>>f[i];
        f[i]='0'+f[i];
    }
    //左上
    ll l=1,r=2*n,z=1,y=2*n;
    ll ans=999999999999999;
    ll cnt=0;
    for(ll i=1;i<=n;i++)
    {
        ll cd=(n-i+1)*2;
        cd=cd+cd-1+cd-1+cd-2;
        cnt+=ck(n-i+1,l,r,z,y,cd);
        l++;
        r--;
        z++;
        y--;
    }
    ans=min(ans,cnt);
   // 左下
    cnt=0;
    l=1,r=2*n,z=1,y=2*n;
    for(ll i=1;i<=n;i++)
    {
        ll cd=(n-i+1)*2;  
        ll k=cd+cd-1+cd-1+(n-i);
        cd=cd+cd-1+cd-1+cd-2;
        cnt+=ck(k,l,r,z,y,cd);
        l++;
        r--;
        z++;
        y--;
    }
    ans=min(ans,cnt);
    //右上
     cnt=0;
     l=1,r=2*n,z=1,y=2*n;
    for(ll i=1;i<=n;i++)
    {
        ll cd=(n-i+1)*2;  ll k=cd+(n-i);
        cd=cd+cd-1+cd-1+cd-2;
      
        cnt+=ck(k,l,r,z,y,cd);
        l++;
        r--;
        z++;
        y--;
    }
    ans=min(ans,cnt);
    cnt=0;
    l=1,r=2*n,z=1,y=2*n;
    for(ll i=1;i<=n;i++)
    {
        ll cd=(n-i+1)*2; ll k=cd+cd-1+n-i;
        cd=cd+cd-1+cd-1+cd-2;
        cnt+=ck(k,l,r,z,y,cd);
        l++;
        r--;
        z++;
        y--;
    }
    ans=min(ans,cnt);
    cout<<ans<<endl;
}

E.小紅開寶箱

思路:賽時不會做,賽後看了思路,是一個樹的圖論,基環樹+拓撲,基環樹我是真不曉得,涉及過淺,後幾天再補上

相關文章