牛客寒假4到6补题

牛客寒假4:

F:来点每日一题

题意:给定一个长度为 n 的数组,任意选6个数,6个数得分为 ((a-b) * c - d) * e - f,问最大能得到多少分
解:n*n的dp,暴力枚举每一个数字 v[i],f[i]表示以第 i 个位置结尾的得分最大是多少
 
复制代码
void solve() {
    int n;
    cin >> n;
    vector<int> v(n+10) , f(n+10);
    for(int i=1;i<=n;i++) cin >> v[i];
    for(int i=1;i<=n;i++) {
        vector<int> minn(10 , INF), maxx(10 , -INF);
        f[i]=max(f[i],f[i-1]);
        for(int j=i;j<=n;j++) {
            for(int k=5;k>=1;k--) {
                for(int p : {minn[k - 1], maxx[k - 1]}) {
                    if(abs(p)<INF) {
                        if(k&1) p-=v[j];
                        else p*=v[j];
                        minn[k]=min(minn[k],p);
                        maxx[k]=max(maxx[k],p);
                    }
                }
            }
            minn[0]=min(minn[0],v[j]);
            maxx[0]=max(maxx[0],v[j]);
            f[j]=max(f[j],f[i-1]+maxx[5]);
        }
    }
    cout << f[n] << endl;
}
View Code
复制代码

 

牛客寒假5:
F:soyorin的数组操作(hard)
题意:有一个长度为n的数组,每次可以选择一个不大于n的偶数k,使得ai(1<=i<=k) 加上 i 。问最少需要操作多少步,可以使得数组非降序排列
解法:最开始写复杂了,想到二分去了,过了80%。
但是正解手画一下就知道了。
在有解的情况下,答案就是 Ai-Ai+1 的最大值,因为相邻两数每次操作只减小1差距,所以在有解的情况下,答案就是两相邻数最小需要达到非降序的操作次数最大值。
复制代码
void solve() {
    int n;
    cin >> n;
    vector<int> v(n+10);
    for(int i=0;i<n;i++) cin >> v[i];
    int ans=0,cnt=0;
    for(int i=n-2;i>=0;i--) {
        if(n&1) {
            if(v[i+1]+cnt<v[i]) {
                cout << -1 << endl;
                return ;
            }
            if((i+1)%2==0) cnt+=(v[i+1]+cnt-v[i])/(i+1);
        }
        ans = max(ans, v[i]-v[i+1]);
    }
    cout << ans << endl;
}
View Code
复制代码

 

K:soyorin的通知

题意:A想要将一条消息传给n个人。有两种操作:要么将消息单独传给一个人,花费p;要么花费 a 的代价将消息传给b个人。

问:将消息传给n个人最少需要多少代价。

解:将问题转换为完全背包看即可,对于代价和体积,题目已经给了,只是在传的时候要保证当前这个人已经知道了消息,即保证第一个人一定是花费p,后面的完全背包跑即可。

复制代码
int f[1010],v[1010],w[1010];

void solve() {
    int n,k;
    cin >> n >> k;
    for(int i=1;i<=n;i++) cin >> v[i] >> w[i] , f[i]=INF;
    f[1]=k;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) f[j]=min({j*k , f[j] , f[max(1ll,j-w[i])]+v[i]});
    }
    cout << min(f[n],n*k) << endl;
}
View Code
复制代码

 

 牛客寒假6:

J:绝妙的平衡

小红拿到了一棵有根树,其中有一些节点被染成了红色。树的根节点是 1 号节点。小红希望你给每个节点的权值赋值为 1 或者 2,需要满足每个红色节点的子树节点权值之和为 3 的倍数。请给出任意一种赋值方案。

解:我们以红点为根节点,将整棵树拆分成一个一个森林来处理。

证明:对于每一个森林,只要每一个单独的和是3的倍数,总和一定是3的倍数。所以任意一个森林都可以独立处理并且和其他森林无关,搜一下每个根节点,特判只有一个根节点为森林的子树为-1即可。

复制代码
string s;
int n,f[N];
queue<int> q;
vector<int> v[N],res;

void dfs(int x) {
    res.push_back(x);
    for(auto & t : v[x]) {
        if(s[t]=='R') q.push(t);
        else dfs(t);
    }
}

void solve() {
    cin >> n >> s;
    s = ' ' + s;
    f[1]=1;
    for(int i=2;i<=n;i++) {
        int x;
        cin >> x;
        v[x].push_back(i);
        f[i]=1;
    }
    q.push(1);
    while(q.size()) {
        int t = q.front();
        q.pop();
        dfs(t);
        if(s[t]=='R') {
            int w = res.size();
            if(w==1) {
                cout << -1 << endl;
                return ;
            }
            int d = w%3;
            if(d==1) f[res[0]]++ , f[res[1]]++;
            else if(d==2) f[res[0]]++;
        }
        res.clear();
    }
    for(int i=1;i<=n;i++) cout << f[i] ;
}
View Code
复制代码

 

F:命运的抉择

小红拿到了一个数组a,以及两个空的数组b和c,她将进行以下操作:对于i∈[1,n],要么将 a添加进数组b,要么添加进数组c。

小红希望b和c满足:bc均非空,两个数组中各任取一个元素bi,ci,均满足gcd(bi,cj)=1gcd(bi,cj)=1你能给出一个添加方案吗?

解:其实就是质因数分解加并查集,赛时写了个搜索T了,难受

直接队第一个数的质因数进行合并,知道某一个数组的数字的质因数只在当前数组有即可。

并查集和set都可以。

复制代码
void solve() {
    int n;
    cin >> n;
    int idx=-1 , w=0;
    set<int> s;
    vector<int> k(n+10),f(n+10);
    for(int i=1;i<=n;i++) {
        cin >> k[i];
        f[i] = k[i];
        s.insert(k[i]);
        if(k[i]==1) idx=i;
        w=max(w,k[i]);
    }
    if(s.size()==1) {
        if(*s.begin()==1) {
            cout << 1 << ' ' << n-1 << endl;
            cout << 1 << endl;
            for(int i=2;i<=n;i++) cout << 1 << endl;
        }
        else cout << -1 << ' ' << -1 << endl;
        return ;
    }
    if(idx!=-1) {
        cout << 1 << ' ' << n-1 << endl;
        cout << 1 << endl;
        for(int i=1;i<=n;i++) {
            if(idx==i) continue;
            cout << k[i] << ' ';
        }
        cout << endl;
        return ;
    }
    
    s.clear();
    vector<int> v[n+10],vis(n+10);
    for(int i=1;i<=n;i++) {
        for(int j=2;j*j<=k[i];j++) {
            if(k[i]%j==0) {
                v[i].push_back(j);
                while(k[i]%j==0) k[i]/=j;
            }
        }
        if(k[i]>1) {
            v[i].push_back(k[i]);
        }
    }
    for(auto & t : v[1]) s.insert(t);
    vis[1]=1;
    bool flag=1;
    while(flag) {
        flag=0;
        for(int i=1;i<=n;i++) {
            if(!vis[i]) {
                for(auto & t : v[i]) {
                    if(s.count(t)) {
                        flag=1 , vis[i]=1;
                        for(auto & x : v[i]) s.insert(x);
                        break;
                    }
                }
            }
        }
    }
    
    int cnt=0;
    for(int i=1;i<=n;i++) if(vis[i]) cnt++;
    if(cnt==n) cout << -1 << ' ' << -1 << endl;
    else {
        cout << cnt << ' ' << n-cnt << endl;
        for(int i=1;i<=n;i++) if(vis[i]) cout << f[i] << ' ';
        cout << endl;
        for(int i=1;i<=n;i++) if(!vis[i]) cout << f[i] << ' ';
        cout << endl;
    }
}
View Code
复制代码
posted @   lzywakaka  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示