【题解】2024牛客多校第5场

E 安

https://ac.nowcoder.com/acm/contest/81600/E

分析

简单博弈 / 思维题。

ai > bi 时,当前骑士一定存活。

ai < bi 时,当前骑士一定死亡。

为了使得自己存活的骑士尽可能多,若存在 ai = bi 的情况,一定会选择令该骑士去攻击对方,并且双方均会轮流优先选择此类骑士。

因此,记 ai > bi 的个数为aa,ai = bi 的个数为bb,则最终存活的棋子即为

a a + ⌈ b b 2 ⌉ aa + \lceil\frac{bb} {2} \rceil aa+2bb

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long long ll;
const ll mod = 998244353;
const int N = 1e5 + 7;

int n;
int a[N],b[N];

void solve(){
    cin >> n;
    for(int i = 1;i <= n;i++) cin >> a[i];
    for(int i = 1;i <= n;i++) cin >> b[i];

    int aa = 0,bb = 0;
    for(int i = 1;i <= n;i++){
        if(a[i] > b[i]) aa++;
        else if(a[i] == b[i]) bb++;
    }

    cout << aa + (bb + 1) / 2 << '\n';
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int T;
    cin >> T;
    while (T--)
    {
        solve();
    }

    return 0;
}

B 珑

https://ac.nowcoder.com/acm/contest/81600/B

分析

多米诺骨牌经典问题。

在这里插入图片描述

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long long ll;
const ll mod = 998244353;
const int N = 1e5 + 7;

int n,m,a,b;

void solve(){
    cin >> n >> m >> a >> b;

    if((n == 1 && m == 2) || (n == 2 && m == 1)){
        cout << "Yes\n";
        return ;
    }

    if((n & 1) && (m & 1)) cout << "No\n";
    else if(b == 1){
        if(a == 1) cout << "Yes\n";
        else if(n == 1 || m == 1) cout << "No\n";
        else cout << "Yes\n";
    } 
    else if(a == 1){
        if(n == 1 && m % 2 == 0) cout << "Yes\n";
        else if(m == 1 && n % 2 == 0) cout << "Yes\n";
        else cout << "No\n";
    }else{
        if(n == 1 && m == 2) cout << "Yes\n";
        else if(n == 2 && m == 1) cout << "Yes\n";
        else cout << "No\n";
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int T;
    cin >> T;
    while (T--)
    {
        solve();
    }

    return 0;
}

L 知

https://ac.nowcoder.com/acm/contest/81600/L

分析

最终答案即为求 a1 * a2 * a3 * … * an 的最大值。

平均分配原则。

ai < ai+1,则给 ai 增加 1,给 ai+1 减少 1,则答案一定不会变劣。

维护前缀和数组c,对于每个ai,计算出[i,i],[i,i+1],[i,i+2]…[i,n]的平均数的最大值s,
若ai < s,则将ai变为s即可。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long long ll;
const ll mod = 998244353;
const int N = 1e7 + 7;
ll a[N];
ll c[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int T;
    cin >> T;
    while (T--)
    {
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
        }
        c[n + 1] = 0;
        for (int i = 1; i <= n; i++)
        {
            c[i] = c[i - 1] + a[i];
        }
        for (int i = 1; i < n; i++)
        {
            ll s = 0;
            for (int j = i + 1; j <= n; j++)
            {
                s = max(s, (a[i] + c[j] - c[i]) / (j - i + 1));
            }
            if (a[i] < s)
            {
                s-=a[i];
                a[i] += s;
                a[i + 1] -= s;
            }
        }
        ll res = 1;
        for (int i = 1; i <= n; i++)
        {
            res *= a[i];
            res %= mod;
           // cout << a[i] << ' ';
        }
        cout << res << '\n';
    }

    return 0;
}

H 入

https://ac.nowcoder.com/acm/contest/81600/H

分析

考虑若每个点只连了一条边,那么最终的方案数只有1个,即走完这条链。

若每个点连了两条边或者更多,每个点连的所有边只有一条会起作用,因此实际起作用的点不用超过n/2,所以直接爆搜,状态数也不会超过2^20约1e6。

注意爆搜时进行记忆化,可以结合状压dp来写,总时间复杂度约 O ( n ∗ 2 n ) O(n * 2^n) O(n2n)

代码

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 42;
struct stu1{
    int y,nex;
}e[N*N];
int n,m,lin[N],cnt,ans;
void work(int x,int y){
    e[++cnt]=(stu1){y,lin[x]}; lin[x]=cnt;
}
unordered_map<LL,int> mp[N];
void Get(int dq){
    for(int i=0;i<n;i++) cout<<((dq>>i)&1);
    cout<<endl;
}
int dfs(LL dq1,int x){

    if(mp[x][dq1]) return max(mp[x][dq1],0);

    LL dq2=dq1;
    for(int i=lin[x];i;i=e[i].nex){
        int y=e[i].y;
       
        if(((dq1>>y-1)&1)==0){
            
            dq2|=(1ll<<y-1);
        }
    } //zouguoqu

    for(int i=lin[x];i;i=e[i].nex){
        int y=e[i].y;
        if(((dq1>>y-1)&1)==0){
            //if(x==6) cout<<y<<endl;
            mp[x][dq1]=max(mp[x][dq1],dfs(dq2,y)+1);
        }
    } //zouguoqu
   // Get(dq1); Get(dq2);
    //cout<<mp[dq1]<<' '<<x<<' '<<dq1<<endl;
    if(!mp[x][dq1]) mp[x][dq1]=-1;
    return max(mp[x][dq1],0);
}
int main()
{  
   scanf("%d%d",&n,&m);
    int x,y;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        work(x,y);
        work(y,x);
    }
    for(int i=1;i<=n;i++) ans=max(ans,dfs((1ll<<i-1),i)+1);
    printf("%d",ans);
}

场上就写出来了这4道,持续补题中…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值