补题:LeetCode第263场周赛&&cf 749

做题一时爽,补题...

2042. 检查句子中的数字是否递增

签到题

class Solution:
    mymax = -1
    def areNumbersAscending(self, s: str) -> bool:
        x_list = s.split()
        for x in x_list:
            if x[0].isdigit() :
                num = eval(x)
                if num <= self.mymax :
                    return False
                else:
                    self.mymax = num

        return True
        

2043. 简易银行系统

模拟题,注意账户不存在的情况

class Bank {
public:
    long long vec[100000+10];
    int len;
    Bank(vector<long long>& balance) {
        len = balance.size();
       for(int i = 0;i < balance.size();i++)
           vec[i+1] = balance[i];
    }
    bool isPre(int account) {
        if(account >=1 && account <= len)  return true;
        return false;
    }
    
    bool transfer(int account1, int account2, long long money) {
        if(isPre(account1) == false || isPre(account2) == false) return false;
        if(vec[account1] < money)  return false;
        vec[account1] -= money;
        vec[account2] += money;
        return true;
    }
    
    bool deposit(int account, long long money) {
        if(isPre(account) == false)  return false;
        vec[account] += money;
        return true;
    }
    
    bool withdraw(int account, long long money) {
        if(isPre(account) == false)  return false;
        if(vec[account] < money)  return false;
        vec[account] -= money;
        return true;
    }
};

/**
 * Your Bank object will be instantiated and called as such:
 * Bank* obj = new Bank(balance);
 * bool param_1 = obj->transfer(account1,account2,money);
 * bool param_2 = obj->deposit(account,money);
 * bool param_3 = obj->withdraw(account,money);
 */

2044. 统计按位或能得到最大值的子集数目

按位或的最大值就是全部或进来,然后在二进制枚举

class Solution {
public:
    int cal(vector<int>& nums) {
        int res = 0;
        for(int num : nums) 
            res |= num;
        return res;
    }
    int countMaxOrSubsets(vector<int>& nums) {
        int mymax = cal(nums);
        // cout << mymax << endl;
        int n = nums.size();
        int res = 0;
        for(int i = 0;i < (1<<n);i++)
        {
            int tmp = 0;
            for(int j = 0; j < n;j++) {
                if(i&(1<<j)) tmp |= nums[j];
            }
            if(tmp == mymax)  res++;
        }
        return res;
    }
};

2045. 到达目的地的第二短时间

其实只需要跳数就能求出所用时间,所以用BFS求出次短路即可

class Solution {
public:
    int secondMinimum(int n, vector<vector<int>>& edges, int time, int change) {
        unordered_map<int, vector<int>>mp(n);
        for(auto edge : edges) {
            int u = edge[0], v = edge[1];
            // cout << u << " " << v << endl;
            mp[u].push_back(v);
            mp[v].push_back(u);
        }
        vector<int>dis(n+1);  // 到1的距离
        queue<int>q;
        while(!q.empty()) q.pop();
        dis[1] = 0;
        q.push(1);
        while(!q.empty()){
            int u = q.front();
            q.pop();
            // cout << "u: " << u << endl;
            if(u == n)  break;
            for(int v : mp[u]){
                // cout << "v: " << v << endl;
                if(dis[v] == 0 && (v!=1)) {
                    dis[v] = dis[u]+1;
                    q.push(v); 
                }
            }
        }
        
        // cout << "******" << endl;

        while(!q.empty()) q.pop();
        q.push(n);
        int res = dis[n];
        bool flag = false;
        while(!q.empty()){
            int sz = q.size();
            for(int i = 0;i < sz;i++) {
                int u = q.front();
                // cout << "u: " << u << endl;
                q.pop();
                for(int v : mp[u]){
                    // cout << "v: " << v << endl;
                    if(dis[v] == res) {flag = true; break;}
                    if(dis[v] == res-1) q.push(v);
                }
            }
            if(flag)  break;
            res--;
        }

        // for(int i = 1;i <= n;i++)  cout << dis[i] << endl;
        int times = flag ? dis[n]+1 : dis[n]+2;
        // cout << "times: " << times << endl;
        int t = 0;  // 当前时间
        while(times--) {
            t += time;
            if(times==0) break;  // 最后一次了就不需要等了
            int tmp = t/change;
            if(tmp%2) { // 奇数,不用等
                t = (tmp+1)*change;
            }
            // cout << "t: " << t << endl;
        }
        return t;
    }
};

 

Codeforces Round #749 (Div. 1 + Div. 2, based on Technocup 2022 Elimination Round 1)

A. Windblume Ode

题意:求最大的子集数,使得子集和为和数,n>=3且每个数互异

思路:先求全部元素之和,如果是合数即为答案;如果不是,则是质数,质数一定是奇数,而n个数中一定存在奇数,所以答案是n-1

#include<cstdio>
#include<iostream>
using namespace std;

int n;
int a[105];

bool isPrime(int num) {
    for(int i = 2;i*i <= num;i++) {
        if(num % i == 0)  return false;
    }
    return n!=1;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d", &n);
        int sum = 0;
        for(int i = 0;i < n;i++) {
            scanf("%d", &a[i]);
            sum += a[i];
        }

        if(!isPrime(sum)) {
            printf("%d\n", n);
            for(int i = 0;i < n;i++)  printf("%d%c", i+1, i == n-1? '\n' : ' ');
        }
        else {
            printf("%d\n", n-1);
            int flag = true;
            for(int i = 0;i < n;i++) {
                if((a[i]%2) && flag) flag=false;
                else printf("%d ", i+1);
                // printf("%c", i==n-1?'\n':' ');
            }
            printf("\n");
        }
    }
}

B. Omkar and Heavenly Tree

题意:有m条限制a b c(意思是b不能位于a到c的最短路径上),构造一个满足所有限制的n个节点的树,m<n

思路:因为m<n,则至少存在一个节点不受限制,把它作为中心,构造一个星型图

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

int n, m;
const int maxn = 100000+10;
bool vis[maxn];

int main(){
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &n, &m);
        memset(vis, 0, sizeof(vis));
        int a, b, c;
        for(int i = 0;i < m;i++) {
            scanf("%d%d%d", &a, &b, &c);
            vis[b] = true;
        }
        int center;
        for(int i = 1;i <= n;i++){
            if(!vis[i]) {
                center = i;
                break;
            }
        }
        for(int i = 1;i <= n;i++) {
            if(i != center) printf("%d %d\n", i, center);
        }
    }
    return 0;
}

C. Omkar and Determination

题意:有点绕,给定一个地图,只能走空格和往上往左走,如果从该格出发能走出去称为exitable,如果给定每个格子的exitable情况,能反推原地图,则称为determinable。现有q次查询, 询问x1~x2列组成的网格是否是可determinable的

思路:

只要存在

     *

*   _

这个结构就不是determinable,如果没有这个结构,就一定可以反推回去。自己想想这个结论

#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
using namespace std;

int n, m;
const int maxn = 1e6+10;
int cols[maxn];
vector<string>maze;

int main(){
    ios::sync_with_stdio(false);
    cin >> n >> m;
    maze.resize(n);

    for(int i = 0;i < n;i++)  cin >> maze[i];

    for(int i = 1;i < n;i++)
        for(int j = 1;j < m;j++) {
            if(maze[i-1][j] == 'X' && maze[i][j-1] == 'X')  cols[j]++;
        }

    for(int i = 1;i <= m;i++)  cols[i] += cols[i-1];

    int q, a, b;
    cin >> q;
    while (q--)
    {
        cin >> a >> b;
        a--, b--;
        if(cols[b]-cols[a])  cout << "NO\n";
        else  cout << "YES\n";
    }
    return 0;
}

D, E,F,G,H,I 补不动了,短期目标是稳定前3道

cf题解都是参考的赛后官方教程

posted @ 2021-10-19 16:33  Rogn  阅读(88)  评论(0编辑  收藏  举报