第二届天元编程邀请赛(提高组)考试总结
T1 石老板举世无双
考试的时候没有往矩阵快速幂和递推方面想,向着去推公式,结果没有推出来。
只写了一个特殊性质和暴力,而暴力因为精度的原因爆掉了,之拿到 \(12pts\)
正解是 递推 + 矩阵快速幂。
设 \(f_i\) 表示 第 \(i\) 次循环 \(check = 0\) 的情况,\(g_i\) 表示 第 \(i\) 次循环 \(check = 1\) 的情况,则有:
这样的递推式子可以拿到 \(60pts\),\(100pts\) 就要求使用矩阵快速幂了。
T2 石老板腾云驾雾
考试思路是 计算所有不能放在一起的点对的数量,然后作减法算出答案。\(O(n^2)\) 的时间复杂度只拿到 \(30pts\)
#include<bits/stdc++.h>
#define MAXN 100010
using namespace std;
typedef long long ll;
ll n,m,ans;
ll a[MAXN];
bool vis[MAXN];
int main(){
scanf("%lld",&n);
for(int i = 1;i <= n;i++) scanf("%lld",&a[i]);
sort(a+1,a+n+1);
m = unique(a + 1,a + n + 1) - a - 1;
ans += n - m;
for(int i = 1;i <= m;i++){
for(int j = i + 1;j <= m;j++){
if(vis[i] && vis[j]) continue;
ll mult = a[i] * a[j],sq = sqrt(mult);
if(sq * sq == mult){
if(!vis[i] && !vis[j]) ans--;
if(!vis[i]) ans++, vis[i] = true;
if(!vis[j]) ans++, vis[j] = true;
}
}
}
printf("%lld\n",n - ans);
}
正解考虑质因数分解(考试的时候第一个把这个想法丢掉),把分解后指数为偶数的去掉,剩下指数为奇数的质数的乘积,也就是把完全平方数因子去掉,最后剩下的如果相等就不能同时出现,也就是将它去重。
对于质因数分解,我们只需要用筛法预处理出 \(p \le 1000\) 的质数,在将每一个数分解并去掉完全平方数因子,最后剩下的数 \(r\) 只有四种情况:
1.\(r = 1\)
2.\(r = p\)
3.\(r = pq\)
4.\(r = p^2\)
其中 \(p,q\) 为互不相等的质数。
为什么次数最多只有 \(2\) 呢?应为除去 \(p \le 1000\) 的质数后,剩下的质数 \(p,q\) 必定有 \(p,q \ge 1000\),那么如果存在三次幂的话一定会大于 \(10^9\),不符合题意。
这样就只需要判读剩下的是否是 \(q^2\),如果是,就将其改成 \(1\) 就好了。
T3.石老板心肌梗塞
考试的时候压根没有思路,只是草草打了一个暴力就滚粗了,只拿到 \(20pts\)。
正解比较难想。先考虑如果有 \(mex_u = k\),那么有
1.对于没有经过该边的路径的权值组成的集合,应当包含权值 \(1\le w \ge k-1\)。
2.对于所有权值为 \(k\) 的路径都应经过该边。
那么我们从小到大枚举权值 \(w\),把当前还没有更新答案的且满足上述条件的边答案都更新为 \(w\)。
T4.石老板魂飞魄散
在考场上想到了采用 并查集 来做,但是不知道如何预处理出与当前修改的极大同色连通块相邻的其他极大同色连通块,因此虽然有正解的想法,最终只是拿到了暴力分。
正解貌似要用到 hash_map 和 list(或set) 来完成,但是这三个 STL 我都没有太常用,所以要研究一下。

浙公网安备 33010602011771号