2023牛客寒假算法基础集训营1

2023牛客寒假算法基础集训营1

2023牛客寒假算法基础集训营1

题目类型官方
A贪心模拟
L期望数学
C贪心诈骗 思维 贪心
H思维诈骗 思维 贪心
K贪心贪心 or 状压dp
D思维贪心 数学 分类讨论
比赛过程 补题过程

A World Final? World Cup! (I)

贪心:即使输方后面全得也没有办法追平分数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kf8dxd8W-1674918506201)(image-ldf9f79o.png)]

#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; i ++ )
#define fors(i, a, b) for(int i = a; i < b; i ++ )
#define deb(x) cout << #x << "=" << x << endl
#define deb2(x, y) cout << #x << "=" << x << ", " << #y << "=" << y << endl

using namespace std;

const int N = 2e5 + 10, mod = 1e9+7;

char a[6], b[6];
typedef pair<int, int> PII;
typedef long long ll;

bool check(int sca, int scb, int k) {
    if(sca > scb) { // b翻盘的机会
            if((k + 1) /2 < (sca - scb)) {
                cout << 10 - k << endl;
                return 1;
            }
        }
    if(sca < scb) { // a翻盘的机会
        if(k/2 < (scb - sca)) {
            cout << 10 - k << endl;
            return 1;
        }
    }
    
    return 0;
}

void run() {
    int k = 10, sca = 0, scb = 0, flag = 0;
    rep(i, 1, 5) cin >> a[i], cin >> b[i]; 
    rep(i, 1, 5) {
        // 第一次
        if(a[i] == '1') sca += 1;
        k -= 1;
        if(check(sca, scb, k)) {
            flag = 1;
            break;
        }                                         
        
         // 第二次
        if(b[i] == '1') scb += 1;
        k -= 1;
        if(check(sca, scb, k)) {
            flag = 1;
            break;
        }
    }
    
    if(flag == 0) cout << -1 <<endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T = 1;
	cin >> T;
	
	while(T -- ) run();

	return 0;
}

L 本题主要考察了运气

期望
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iRzzncpi-1674918506202)(image-lde1rav7.png)]

C 现在是,学术时间 (I)

贪心

#include <bits/stdc++.h>

using namespace std;
signed main() {
    int t = 1;
    cin >> t;
    while(t -- ) {
        int n, i, x, sum = 0; cin >> n;
        for (i = 1; i <= n; i ++ ) {
            cin >> x;
            if(x != 0) sum += 1;
        }
        cout << sum << endl;
    }
}

H 本题主要考察了DFS

思维:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VON548K5-1674918506202)(image-lde48rn5.png)]
:::note
标记技巧:一个拼图块可以由一个长度为4的字符串描述,四个字符分别表示上、右、下、左四条边进行的操作,上述三种操作依次记为0,1,2、
:::

#include <iostream>
using namespace std;
void run() {
    int n, i, x = 0, y = 0; cin >> n;
    char ch;
    for (i = 1; i <= n*n*4 - 4; i ++ ) {
        cin >> ch;
        if(ch == '1') x += 1;
        if(ch == '2') y += 1;
    }
    
    cout << 10 + x - y << endl;
}

int main() {
    int t; cin >> t;
    while(t -- ) run();
}

K 本题主要考察了dp

贪心

#include <iostream>
#define deb(x) cout << #x << "=" << x << endl
#define deb2(x, y) cout << #x << "=" << x << ", " << #y << "=" << y << endl
using namespace std;
signed main() {
    int n, m, x; cin >> n >> m;
    x = n - m; // m-1, x-0
    if(m <= n/3) cout << 0 << endl;
    else if(n == m) cout << n-2 << endl;
    else {
        m -= x/2;
        x = x%2;
        //deb2(m,x);
        if(x == 0 && m == 1) cout << 0 << endl;
        else cout << m - 2 + 1;
    }
}

D 现在是,学术时间 (II)

思维:(看)先求出另外矩形的大小,在求交集, s = s= s=两个矩形 − - 交集

#include <bits/stdc++.h>
using namespace std;         

void run() {
  int x, y, xp, yp, s, a, b;
  cin >> x >> y >> xp >> yp;
  a = max(abs(xp - x), xp);
  b = max(abs(yp - y), yp);
  s = a * b + x * y;
  a = min(a, x);
  b = min(b, y);
  double ans;
  ans = double(a * b) / (s - a * b);
  printf("%.9f\n", ans);
}

int main() {
    int t = 1;
    cin >> t;
    while(t-- ) run();
}

补题重现赛

题目类型官方
Mdpdp(背包)
F图论思维 基础图论 BFS

M 本题主要考察了找规律

就是很典型的dp,枚举一下就可以了

#include <bits/stdc++.h>
using namespace std;

double dp[510][510]; // 前i个人共分得j个仙贝的最大好感度

signed main() {
    int n, m, i, j, k; cin >> n >> m;
    for (i = 1; i <= n; i ++ )
    for (j = 1; j <= m; j ++ )
    for (k = 1; k <= j; k ++ )
        dp[i][j] = max(dp[i][j], dp[i-1][j-k] + k*1.0 / (m - j + k));
    
    printf("%.9lf", dp[n][m]);
}

F 鸡玩炸蛋人

图论+结论+转化 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FrTrXueM-1674918506203)(image-ldfcjo5j.png)]

:::danger
开不了这么大的内存,白写
:::

#include <bits/stdc++.h>
using namespace std;

int g[100010][100010];
int vis[100010];
int w[100010];
int n;

typedef pair<long long, bool> PII;

PII bfs(int s) {
    int i;
    queue<int> q; q.push(s);
    PII t = {0, 0};
    while(!q.empty()) {
        int k = q.front();
        for (i = 1; i <= n; i ++ ) {
            if(g[k][i] == 1 && vis[i] == 0) {
                vis[i] = 1;
                q.push(i);
                t.first += 1;
                if(w[i] != 0) t.second = 1;
            } 
        }
    }
    return t;
}

signed main() {
    int m, i, sum = 0, x, y, flag = 0; cin >> n >> m;
    long long ans = 0;
    for (i = 0; i < m; i ++ ) {
        cin >> x >> y;
        g[x][y] = 1, g[y][x] = 1;
    }
    for (i = 1; i <= n; i ++ ) {
        cin >> w[i];
        if(w[i] != 0) flag = 1;
    }
    for (i = 1; i <= n; i ++ ) {
        if(vis[i] != 0) { // 如果当前没搜过那就搜完这个连通块
            PII t =  bfs(i);
            if(t.second == 1) ans += t.first * t.first, sum += 1;
        }
    }
    // 第一种:没有砸蛋
    if(flag == 1) cout << ans << endl; 
    // 第二种,有一个连通块有砸蛋
    else if(sum == 1) cout << ans << endl;
    cout << 1 << endl;
}

:::danger
超时了,可能是map的原因
:::

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IfiMBtIQ-1674918506203)(image-ldfg5to4.png)]

#include <bits/stdc++.h>
#define deb(x) cout << #x << "=" << x << endl
#define deb2(x, y) cout << #x << "=" << x << ", " << #y << "=" << y << endl
using namespace std;
const int N = 1e5 + 10, M = 4e5 + 10;
    
int h[N], e[M], ne[N], idx = 0;
int w[N], vis[N], sud;
long long ans, ans2;
map<pair<int, int>, bool> mp;

void bfs(int i) {
    long long flag = 0, vsum = 1;
    queue<int> q; q.push(i);
    vis[i] = 1; 
    if(w[i] != 0) sud += 1,flag = 1;
    while(!q.empty()) {
        int t = q.front();
        q.pop();
        for (int i = h[t]; i != -1; i = ne[i]) {
            int y = e[i];
            // deb2(t, y);
            if(vis[y] == 0) { 
                vis[y] = 1, vsum += 1;
                if(w[i] != 0 && flag == 1) sud += 1, flag = 1;
            }
        }
    }
    if(flag == 1) ans2 = vsum * vsum;
    ans += vsum * vsum;
    // deb2(vsum, ans);
}

void add(int x, int y) {
    e[ ++idx] = y, ne[idx] = h[x], h[x] = idx;
    // cout << x << ' '<< y<< ' ' << ne[idx] << endl;
}

signed main() {
    ios::sync_with_stdio(false);
	cin.tie(0);
    int n, m, i, x, y; cin >> n >> m;
    for (i = 0; i < n; i ++ ) h[i] = -1, vis[i] = 0;
    for (i = 0; i < m; i ++ ) {
        cin >> x >> y;
        if(mp[{x, y}] == 0 && mp[{y, x}] == 0)
        {
            add(x, y), add(y, x);
            mp[{x, y}] = 1; mp[{y, x}] = 1;
        }
    }
    for (i = 1; i <= n; i ++ ) cin >> w[i];
    
    for (i = 1; i <= n; i ++ ) {
        if(vis[i] == 0) {
            bfs(i);
        }
    }
    
    if(sud == 0) cout << ans << endl;
    if(sud == 1) cout << ans2 << endl;
    if(sud > 1)cout << 0 << endl;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9;
const ll mm=2e5+10;
vector<int>v[mm];
int dan[mm],use[mm];
int dfs(int x){
	int mi=0;
	queue<int>q;
	q.push(x);use[x]=1;
	while(q.size()){
		int now=q.front();
		q.pop();
		mi++;
		for(auto i:v[now]){
			if(use[i])continue;
			else use[i]=1,q.push(i);
		}
	}return mi;
}
int main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	int mi=0;
	for(int i=1;i<=n;i++)cin>>dan[i],mi=max(mi,dan[i]);
	if(mi){
		ll bj=0;
		for(int i=1;i<=n;i++){
			if(dan[i]){
				bj=dfs(i);
				break;
			}
		}
		for(int i=1;i<=n;i++){
			if(dan[i]&&use[i]==0){
				cout<<0;
				return 0;
			}
		}cout<<bj*bj;
	}else{
		ll ans=0;
		for(int i=1;i<=n;i++){
			if(!use[i]){
				ll t=dfs(i);
				ans+=t*t;
			}
		}cout<<ans;
	}
}
#include<bits/stdc++.h>
#define x first
#define y second
#define int long long 
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 1e5 + 10, mod = 1e9 + 7;
using namespace std;
typedef pair<int, int>PII;
 
int n, p[N], sz[N], m, cnt[N];
int find(int x)
{ 
   if(p[x] != x) 
   p[x] = find(p[x]);
    return p[x]; 
}
void solve()
{
    cin >> n >> m;
     
    for(int i = 1; i <= n; i ++ ) p[i] = i, sz[i] = 1;
     
    while(m -- )
    {
        int u, v;
        cin >> u >> v;
        u = find(u), v = find(v);
        if(u != v)
        {
         sz[v] += sz[u];
         p[u] = v;
        }
    }
    int x, res = 0;
    for(int i = 1; i <= n; i ++ )
    {
        cin >> x;
        if(x) cnt[find(i)] ++, res ++;
    }
    int ans = 0;
    for(int i = 1; i <= n; i ++ )
        if(find(i) == i && cnt[i] == res) ans += sz[i] * sz[i];
     
    cout << ans << '\n';
}
signed main()
{
    io;
    int T = 1;
    while(T -- )
    solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值