首页 > 其他分享 >The 10th Shandong Provincial Collegiate Programming Contest

The 10th Shandong Provincial Collegiate Programming Contest

时间:2024-10-06 22:44:30浏览次数:7  
标签:Provincial Shandong 题意 Contest int 代码 long ++ solve



A - Sekiro

题意

初始有\(n\)个金币,死了\(m\)次,死一次\(n = \lceil \frac n 2 \rceil\)。求最后的金币数。

思路

模拟。

代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long

void solve()
{
	int n, m;
	cin >> n >> m;
	while (m-- && n > 1)
	{
		n = (n + 1) >> 1;
	}
	cout << n << endl;
}

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

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

	return 0;
}

B - Median

题意

\(n\)个数(\(n\)是奇数),\(m\)对关系(\(u v\)表示\(u > v\)),对于第\(i\)个元素,给每个元素赋值,能使它成为中位数就输出\(1\),否则输出\(0\)。

思路

一条关系可以看作一条有向边,由大的指向小的,得到一张有向图,先判断有无环,有环说明情况不存在全为\(0\),可用\(bfs\)或\(dfs\)判断,同时记录该点的前继和后继,若该点为中位数,说明该点的前继和后继都不超过\(\frac n 2\)。

代码

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long

const int mxn = 110;

int n, m, cnt;
vector<int>g1[mxn], g2[mxn];
int up[mxn], low[mxn], deg[mxn], vis[mxn];

void dfs1(int u, int fa) 
{
    vis[u] = 1;
    for (auto v : g2[u]) 
    {
        if (!vis[v]) 
        {
            cnt++;
            dfs1(v, u);
        }
    }
}

void dfs2(int u, int fa) 
{
    vis[u] = 1;
    for (auto v : g1[u])
    {
        if (!vis[v])
        {
            cnt++;
            dfs2(v, u);
        }
    }
}

bool topo() {
    cnt = 0;
    queue<int>q;
    for (int i = 1; i <= n; i++) 
    {
        if (deg[i] == 0)
        {
            q.push(i);
        }
    }
    while (!q.empty()) 
    {
        int u = q.front();
        q.pop();
        cnt++;
        for (auto v : g1[u])
        {
            if (--deg[v] == 0)
            {
                q.push(v);
            }
        }
    }
    return cnt == n;
}

void init() 
{
    for (int i = 1; i <= n; i++) 
    {
        g1[i].clear();
        g2[i].clear();
        deg[i] = 0;
        up[i] = 0;
        low[i] = 0;
    }
}


void solve()
{
    cin >> n >> m;
    init();
    for (int i = 1; i <= m; i++) 
    {
        int u, v;
        cin >> u >> v;
        g1[u].push_back(v);
        g2[v].push_back(u);
        deg[v]++;
    }
    if (!topo()) 
    {
        for (int i = 1; i <= n; i++) 
        {
            putchar('0');
        }
        putchar('\n');
        return;
    }
    for (int i = 1; i <= n; i++) 
    {
        for (int j = 1; j <= n; j++)
        {
            vis[j] = 0;
        }
        cnt = 0;
        dfs1(i, -1);
        up[i] = cnt;
        for (int j = 1; j <= n; j++) 
        {
            vis[j] = 0;
        }
        cnt = 0;
        dfs2(i, -1);
        low[i] = cnt;
    }
    for (int i = 1; i <= n; i++) 
    {
        if (up[i] < (n + 1) / 2 && low[i] < (n + 1) / 2) 
        {
            putchar('1');
        }
        else 
        {
            putchar('0');
        }
    }
    putchar('\n');
}

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

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

    return 0;
}


C - Tokens on the Segments

题意

\(n\)条线段,其中第\(i\)段的端点是\((l_i, i)\)和\((r_i, i)\),在平面的整数点放标记,但是标记的\(x\)坐标必须彼此不同。问最多有多少条线段上有标记。

思路

按如下方法将线段存入小根堆:左端点靠前的在前,左端点一样的,右端点靠前的在前。从最左边的线段的左端点开始计数,用指针记录当前位置。指针右移,同时更新其他线段的左端点(因为标记的\(x\)不能相同),到新的线段就\(ans++\),当前位置没有线段就直接移动到下一条线段。

代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long

struct edge
{
	int l, r;
	bool operator < (const edge& a) const
	{
		if (l == a.l)
		{
			return r > a.r;
		}
		return l > a.l;
	}
};

void solve()
{
	int n;
	cin >> n;
	priority_queue<edge, vector<edge>> q; // 小根堆
	for (int i = 0; i < n; i++)
	{
		int l, r;
		cin >> l >> r;
		q.push({ l,r });
	}
	int now = 1, ans = 0; // 当前可以标记的位置
	while (!q.empty())
	{
		int l = q.top().l;
		int r = q.top().r;
		q.pop();
		if (r >= now) // 右端点>=now就可以标记,且尽量往左标—,所以要更新左端点
		{
			ans++;
			if (l < now) // 标记处在线段左边(与上一条之间有空)
			{
				now = l + 1;
			}
			else
			{
				now++;
			}
		}
		while (q.size() && q.top().l == l) // 更新左端点
		{
			edge t = q.top();
			q.pop();
			t.l++; // 前推1
			if (t.l <= t.r) // 仍然是线段(或者点)
			{
				q.push(t);
			}
		}
	}
	cout << ans << endl;
}


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

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

	return 0;
}

D - Stones in the Bucket

题意

\(n\)个桶,第\(i\)个桶里有\(a_i\)个石头。两种操作:从非空同种一走一个石头、把一个桶里的石头移到另一个桶里。问使得所有桶里石头数相同所需的最小操作数。

思路

模拟。

代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long

void solve()
{
	int n, sum = 0;
	cin >> n;
	vector<int> v(n);
	for (int i = 0; i < n; i++)
	{
		cin >> v[i];
		sum += v[i];
	}
	if (n == 1)
	{
		cout << 0 << endl;
		return;
	}
	int ans = sum % n; // 剩下的
	sum /= n; // 平均分
	for (int i = 0; i < n; i++)
	{
		if (v[i] != sum && v[i] < sum) // 少的多的看一半就行
		{
			ans += (sum - v[i]);
		}
	}
	cout << ans << endl;
}

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

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

	return 0;
}

E - BaoBao Loves Reading

题意

思路

代码

点击查看代码


F - Game on a Graph

题意

给定\(n\)个顶点\(m\)条边的简单连通图,\(k\)个人已知分队,轮流删边,使得图不连通的队伍输。两个队伍用最佳策略游戏,问哪队赢。

思路

连通图至少有\(n-1\)条边,也就是说谁能删\(m-(n-1)\)条边。

代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long

void solve()
{
	int n, m, k;
	string s;
	cin >> k >> s >> n >> m;
	for (int i = 0; i < m; i++)
	{
		int u, v;
		cin >> u >> v;
	}
	int idx = (m - n + 1) % k;
	cout << (s[idx] == '1' ? '2' : '1') << endl;
}


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

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

	return 0;
}

B - Median

题意

思路

代码

点击查看代码


H - Wandering Robot

题意

一个在\((0,0)\)机器人每次能够上/下/左/右移动一个单位,用\(U/D/L/R\)表示。已知长度为\(n\)的操作序列,以及重复操作了\(k\)次,求移动过程中机器人到点\((0,0)\)的曼哈顿距离的最大值。
曼哈顿距离:\(|x1−x2|+|y1−y2|\)。

思路

答案一定在第一次操作或第\(k\)次操作中,因为如果第一轮结束导致答案增大,那就会一直增大直至第\(k\)次操作结束;如果减小,之后也会一直减小。

代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long

int n, k;
string cmd;

void move(int& x, int& y, int& ans)
{
	for (int i = 0; i < n; i++)
	{
		switch (cmd[i])
		{
		case 'U':
			y++;
			break;
		case 'D':
			y--;
			break;
		case 'L':
			x--;
			break;
		case 'R':
			x++;
			break;
		default:
			break;
		}
		ans = max(ans, abs(x) + abs(y));
	}
}

void solve()
{
	cin >> n >> k >> cmd;
	int x = 0, y = 0, ans = 0;
	move(x, y, ans);
	int kx = (k - 1) * x, ky = (k - 1) * y; // (k - 1)次操作后的坐标
	move(kx, ky, ans);
	cout << ans << endl;
}


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

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

	return 0;
}

K - Happy Equation

题意

思路

代码

点击查看代码


M - Calandar

题意

定义一年有\(12\)个月,每月\(30\)天,每周\(5\)天(周五之后是周一)。已知今天是\(y_1\)年\(m_1\)月\(d_1\)日和周几,求\(y_2\)年\(m_2\)月\(d_2\)日是周几。

思路

算日期差值后取模即可。

代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long

string week[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };

void solve()
{
	int y1, y2, m1, m2, d1, d2;
	string w;
	cin >> y1 >> m1 >> d1 >> w >> y2 >> m2 >> d2;
	int num1 = y1 * 12 * 30 + m1 * 30 + d1;
	int num2 = y2 * 12 * 30 + m2 * 30 + d2;
	int dt = (num2 - num1) % 5;
	int id = 0;
	for (int i = 0; i < 5; i++)
	{
		if (w == week[i])
		{
			id = i;
			break;
		}
	}
	cout << week[(id + dt + 5) % 5] << endl;
}


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

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

	return 0;
}


比赛链接 <>

标签:Provincial,Shandong,题意,Contest,int,代码,long,++,solve
From: https://www.cnblogs.com/Seii/p/18449231

相关文章

  • AtCoder Beginner Contest 374
    省流版A.判断末三位即可B.逐位判断即可C.枚举所有分组情况即可D.枚举线段顺序、端点顺序即可E.二分答案,发现贵的机器数量不超过\(100\),枚举求最小花费看是否可行即可F.朴素DP,复杂度分析得到有效时刻不超过\(O(n^2)\)而非\(O(s_i)\),直接\(DP\)即可A-Takahashi......
  • 2017中国大学生程序设计竞赛 - 女生专场(SDKD 2024 Summer Training Contest K2)
    A-AutomaticJudge题意\(n\)个问题,\(m\)条记录,每条记录有题号、时间、状态,第一次\(AC\)的时候计入罚时,其他没发罚\(20\)分钟。求队伍过题数和罚时。思路模拟。代码点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvoidsolve()......
  • The 2024 CCPC Shandong Invitational Contest and Provincial Collegiate Programmin
    比赛链接C.ColorfulSegments2考虑最小的分组数量,可以先按左端点排序,然后每次贪心地找到前面一个最大右端点\(r_j<l_i\)的组加入。考虑计数,还是同样地按左端点排序,那么假设现在有\(k\)个组,每个组最大右端点是\(g_i\)(没有元素则\(g_i=0\)),那么每次可以选择一个\(g_j......
  • The 2024 CCPC Shandong Invitational Contest and Provincial Collegiate Programmin
    Preface传说中被杭电1h十题的比赛,结果打到结束也只会10题这场开局就不太顺,一个Easy题C卡到2h的时候才出,虽然中期题基本都能想到但还是出的很慢最后1h讨论了下L的大致做法发现了几个关键性质后觉得写不完了,遂摆烂滚去打炉石了A.Printer签到,二分答案大力检验即......
  • The 2021 ICPC Asia Shenyang Regional Contest
    B-BitwiseExclusive-ORSequence题意\(n\)个数,\(m\)个关系,每个关系形如\(a_u⊕a_v=w\),表示第\(u\)个数与第\(v\)数的异或运算结果为\(w\)。求是否有这样的\(n\)个数满足所有关系要求,如果没有输出\(-1\),如果有输出所有满足要求的方案中,所有数字的和的最小值。思路建图......
  • Skills - 2022 International Collegiate Programming Contest, Jinan Site, Problem
    有3种技能,\(n(\le10^3)\)天内每天可以对一个技能进行学习,第i天学习第j个技能可以为第j个技能增加\(a_{i,j}(\le10^4)\)的熟练度。在第i天结束时,每个技能的熟练度会减去距离上次学习该技能的天数,但最多减到0。求n天后能得到的熟练度的和的最大值。首先容易有一个显然的dp状态:\(f......
  • AtCoder Beginner Contest 373
    省流版A.暴力即可B.求出字母位置,绝对值相加即可C.显然答案为两个数组的最大值的和D.注意直接BFS的点权范围不超过题目范围,直接BFS即可E.发现单调性,二分票数,用前缀和\(O(1)\)判断可行性即可F.朴素背包DP,相同重量的物品一起考虑,用优先队列求解\(l\)个相同重量物品最大......
  • The 2023 ICPC Asia Macau Regional Contest
    A.(-1,1)-Sumplete首先只取\(-1\),这样的话选1和不选-1产生的贡献就是都是+1。枚举每一行,然后贪心选择需求最大的若干列。#include<bits/stdc++.h>usingnamespacestd;usingi32=int32_t;usingi64=longlong;#defineinti64usingvi=vector<int>;usingpi......
  • The 2024 Guangdong Provincial Collegiate Programming Contest
    Preface这场据说题挺毒的?但实际打的时候感觉也还好,3h就出了7个题,然后被H卡飞了赛后发现是没有观察到构造的解的性质,把Dinic换成匈牙利就过了,只能说对flow的理解不够B.腊肠披萨神秘string题,被徐神开场一眼秒了,虽然中间我和祁神上去写了三个签到,但徐神还是在1h不......
  • AtCoder Beginner Contest 365
    A-LeapYear思路模拟即可;AC代码#include<bits/stdc++.h>#defineendl'\n'#defineintintlonglong#definepbpush_back#definebsbitsetusingnamespacestd;typedefpair<char,int>PCI;typedefpair<......