2023.12.28 模拟赛复盘

发布时间 2024-01-01 14:11:52作者: 单南松

T1 sequence

Question

请构造一组长度为 \(n\) 的数列 \(S\),满足题目给出的 \(m\) 个数对 \((a, b)\) 所对应的 $S_a ≠ S_b \(,若存在多组解,请输出十进制下最小的那组。\)n,m$ 均不超过 \(200\),并且保证答案中的任何一位不超过 \(4\)

Solution

第一眼拿到题目,人是傻的,上来就有一个逆天想法:

将原题转化成一个图,\(a, b\) 建一个双向边。凡是建了边的点权值不能一样,暴力染色,中途如果遇到矛盾就表示冲突了。想到之后就开始莽了。然后样例调不过。T1 都不会写还考个毛线。后来观察发现数据很小,想到了 \(dfs\) ,但是复杂度有点高,考虑优化,构造几组数据发现对于完全随机的数据,基本不可能在输出的答案中出现 \(4\),最大就是 \(3\)。接着优化,考虑折半搜索,将答案存成字符串,然后哈希一个值,最后找合法中的哈希值最小的那个。考试过了四十分钟了,T1 小样例过了,大样例 T 了。。。。。

之后发现自己是个小丑,这个题的数据范围就是个幌子,想到了一个贪心,将所有的数对排序,如果 \(S[a_i] = S[b_i]\), 则 \(S[b_i]\) 加一。结果大样例中有两位没对上。之后就开下一题了。

赛后测了一下,这个想法可以过 40pts:

int n, m;
struct node
{
    int l, r;
}a[N];
bool cmp(node a, node b)
{
	return a.l < b.l;
}
int f[N];
signed main()
{
	cin >> n >> m;
	for (rint i = 1; i <= m; i++)
	{
		cin >> a[i].l >> a[i].r;
		if (a[i].l > a[i].r) swap(a[i].l, a[i].r);
	}
	sort(a + 1, a + m + 1, cmp);
	for (rint i = 1; i <= m; i++)
	{
		if (f[a[i].l] == f[a[i].r])
		{
			f[a[i].r]++;
		}
	}
	for (rint i = 1; i <= n; i++)
	{
		cout << f[i] + 1;
	}
	return 0;
}

赛后发现自己的大体想法接近正解了,考虑在排序的基础上 \(dfs\)dfs(int k, int p)k 表示位数, p 表示当前可摆放的最小值。之后 \(v[i][j]\) 表示第 \(i\) 位上能否放 \(j\) 这个数,然后就过了。

int n, m;
bool v[N][5];
//v[i][j] 表示第 i 位上能否放 j 这个数
struct node
{
    int l, r;
} a[N];
bool cmp(node a, node b) 
{ 
    return a.l < b.l; 
}
void dfs(int k, int p)
//k 表示位数, p表示当前可摆放的最小值
{
    int x = 0, pos;
	if (k > n) return;
	for (rint i = 1; i <= 4; i++)
    {
        if (v[k][i])
        {
            pos = i;
            break;
        }		
    }
    cout << pos;
    for (x = p; a[x].l == k; x++)
    {
        v[a[x].r][pos] = 0;
    }
    dfs(k + 1, x);
}

signed main()
{
    cin >> n >> m;
    memset(v, 1, sizeof v);
	for (rint i = 1; i <= m; i++)
    {
		cin >> a[i].l >> a[i].r;
        if (a[i].l > a[i].r) swap(a[i].l, a[i].r);
    }
	sort(a + 1, a + m + 1, cmp);
	dfs(1, 1);
	return 0;
} 

expr

Question

给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。表达式长度不超过 \(10^6\),答案取后四位。

Solution

这才是签到题嘛!用个栈模拟一下,顺手对 \(1000\) 取模就好。

tree

Question

求出给定的树的最大对称二叉子树的节点数。数的节点个数不超过 \(10^6\)

Solution

第一眼觉得是个难题,后来再读题发现纯水题一道。

便枚举便更新答案即可,如果枚举到的这个子树(先不管它是不是对称的)大小比当前更新到的答案小直接去掉即可,否则递归找答案,更新答案。

Revegetation

Question

一场漫长的干旱使农场主约翰的 \(N\) 个牧场没有草。然而,随着雨季的到来,是时候“重新种植”了。在农夫约翰的小屋里,他有两个桶,每个桶都有不同类型的草籽。他想在他的每一个牧场种草,在每一个牧场中选择一种类型的草。

作为一名奶农,农场主约翰想确保他能满足他那几头奶牛的特殊饮食需求。他的 \(m\) 头奶牛都有两个最喜欢的牧场。他的一些奶牛有一个饮食限制,那就是他们应该只吃一种类型的草,因此农场主约翰希望确保在这类奶牛最喜欢的两个田里种植同一种类型的草。其他的奶牛有一个不同的饮食限制,要求他们吃不同类型的草。对于那些奶牛,农场主约翰当然想确保他们最喜欢的两块田地里有不同的草。

请帮助农场主约翰确定他在他的 \(N\) 个牧场上种植草的不同方式的数量。

Solution

模拟赛考试时间就仨小时,根本没时间写 T4。

考虑并查集,此题跟团伙,关押罪犯思路基本一样,相同种的草是不打架的,不同的就打架。但是恶心的地方在于直接这么写就寄掉了,赛时根本没好好看,就十分钟了,随手乱搞了一下没过样例,发现并非所有的牧场一定为任意一只奶牛所喜爱,所以还得再开一个并查集牧场联通性。