2022.9.7 第一次vp

场次

https://codeforces.com/gym/102966

部分题解

B

B. Baking Lucky Cakes

题意:给你 \(n (n <= 10^3)\) 个点,求这些点最多构成多少不退化的三角形

思路是首先找到最多点同时在的一条直线(\(mx\) 是直线上最多的点的数量)

容易发现当 \(2 * n >= 3 * mx\) ,答案是\(n / 3\);否则是 \(min(mx / 2, n - mx)\)

点击查看代码
// #pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define pb push_back
using namespace std;
 const int N = 1005;
int t, n, m;
vector<pii> a;

inline ll cross(pii a, pii b) {   //叉积
	return (1ll * a.first * b.second - 1ll * b.first * a.second);
}

inline int xiangxian(pii a) {
	if(a.first > 0 && a.second >= 0) return 0;
	else if(a.first <= 0 && a.second > 0) return 1;
	else if(a.first < 0 && a.second <= 0) return 2;
	else if(a.first >= 0 && a.second < 0) return 3;
}

inline bool cmp(pii b, pii c) {
	int fb = xiangxian(b);
	int fc = xiangxian(c);
	if(fb == fc) {
		if(fb == 0) return cross(b, c) > 0;
		if(fb == 1) return cross(b, c) < 0;
		if(fb == 2) return cross(b, c) < 0;
		if(fb == 3) return cross(b, c) > 0;
	}
	else 
		return xiangxian(b) < xiangxian(c);
}

int main(){
    scanf("%d", &n);
	for(int j = 1, x, y; j <= n; j++) {
		scanf("%d%d", &x, &y);
		a.push_back({x, y});
	}
	if(n < 3) {
		puts("0");
		system("pause");
		return 0;
	}
	int mx = 0;
	vector<pii> b(n + 5);
	for(int cur = 0; cur < n; cur++) {
		for(int i = 0, j = 0; i < n; i++) {
			if(i != cur) b[j++] = {a[i].first - a[cur].first, a[i].second - a[cur].second};
		}

		sort(b.begin(), b.begin() + n - 1, cmp);

		int cnt = 1;
		for(int i = 1; i < n - 1; i++) {
			if(cross(b[i], b[i - 1]) == 0) {
				cnt++;
			}
			else {
				mx = max(mx, cnt + 1); 
				cnt = 1;
			}
		}
		mx = max(mx, cnt + 1);
	}
	if(2 * n >= mx * 3) printf("%d\n", n / 3);
	else printf("%d\n", min(mx / 2, n - mx));
    system("pause");
    return 0;
}

C

C. CLETS Patrols
读完题意然后发现就是矩阵快速幂。

原始矩阵 \(init\)\(m\) 次幂,然后 \(init[1][i]\) 就表示 \(1\)\(i\) 的概率

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 206;
int a,b,n, m;
struct Matrix{
	double m[maxn][maxn];
};

Matrix mul(Matrix a,Matrix b, int N){
	Matrix c;
	for(int i=0;i<N;i++){  //NxN�ľ��� 
		for(int j=0;j<N;j++){
			c.m[i][j]=0;
		}
	}
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			for(int k=0;k<N;k++){
				c.m[i][j] += a.m[i][k]*b.m[k][j];
			}
		}
	}
	return c;
}

Matrix ksm(Matrix a,int t, int N){   //t����Ҫ��longlong 
	Matrix ans;
	for(int i=0;i<N;i++){  //NxN�ľ��� 
		for(int j=0;j<N;j++){
			if(i==j) ans.m[i][j]=1; 
			else ans.m[i][j]=0;
		}
	}
	while(t){
		if(t&1){
			ans=mul(ans,a, N);
		}
		a=mul(a,a, N);
		t/=2;
	}
	return ans;
}

int main(){
	// while(cin>>a>>b>>n){
	
	Matrix init;
	scanf("%d%d", &n, &m);
	for(int i = 0; i < n; i++) {
		for(int j = 0; j < n; j++) {
			scanf("%lf", &init.m[i][j]);
		}
	}
	Matrix ans=ksm(init, m, n);
	for(int i = 0; i < n; i++) {
		printf("%.10f\n", ans.m[0][i]);
	}
	// }
	return 0;
}

D

D. Determine the Winner Marshaland

打表可发现,\(2^{p_i} \mod p_i == 2\)

因此只需要对 $ k + 2$ 进行质因数分解

点击查看代码
// #pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define pb push_back
using namespace std;
const int N = 1e6 + 10;
int t, n, m;
int a[N];

int p[N], cnt = 0;
bool isp[N];
void init(int N) {
	for (int i = 2; i <= N; ++i) {
		if (!isp[i]) p[++cnt] = i;
		for (int j = 1; j <= cnt && p[j] * i <= N; ++j) {
			isp[i * p[j]] = 1;
			if (i % p[j] == 0) break;
		}
	}
}

int main(){
    init(1000);
	cin >> t;
	while(t--) {
		cin >> n;
		n += 2;
		vector<int> ans;
		for(int i = 1; i <= cnt; i++) {
			if(1ll * p[i] * p[i] > n) break;
			if(n % p[i] == 0) {
				if(p[i] > 2) ans.push_back(p[i]);
				while(n % p[i] == 0) n /= p[i];
			}
		}
		if(n > 1) ans.push_back(n);
		if(ans.empty()) {
			puts("-1");
			continue;
		}
		for(auto i : ans) {
			printf("%d", i);
			if(i == ans.back()) puts("");
			else printf(" ");
		}
	}
    system("pause");
    return 0;
}

E

E. Enterprise Recognition Program

给定一些点的父子关系,然后有两种操作:单点加和链加(从当前点加到根),两种询问:单点答案和子树答案

由于是先操作完了再询问最终结果,因此可以利用树上差分,每次操作时标记一下,最后做dfs即可 \(O(n)\) 求出最后答案

点击查看代码
// #pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define pb push_back
using namespace std;
const int N = 1e6 + 10;
int t, n, m, q;
int root;
vector<int> e[N];
ll d[N]; //d: single
ll tot[N]; // tot: all
ll v[N];

// 1.建树
// 2.首先处理 op , 树上差分 , dfs求出总的(同时编号(便于之后lb
// 3.print op1:single  op2:subtree

void dfs(int now, int fa) { //求single
	for(auto i : e[now]) {
		if(i == fa) continue;
		dfs(i, now);
		d[now] += d[i];
	}
}

void dfs2(int now, int fa) {  //求tot
	for(auto i : e[now]) {
		if(i == fa) continue;
		dfs2(i, now);
		tot[now] += tot[i];
	}
}

int main(){
	scanf("%d%d%d", &n, &m, &q);
	for(int i = 1, x; i <= n; i++) {
		scanf("%d", &x);
		if(!x) {
			root = i;
		}
		else {
			e[x].push_back(i);
		}
	}
	for(int i = 1, op, pos, v; i <= m; i++) {
		scanf("%d%d%d", &op, &pos, &v);
		if(op == 2) {  //链加
			d[pos] += v;
		}
		else { //单点加
			tot[pos] += v;
		}
	}
	dfs(root, root);
	for(int i = 1; i <= n; i++) {
		tot[i] += d[i];
		v[i] = tot[i];
	}
	dfs2(root, root);
	for(int i = 1, op, pos; i <= q; i++) {
		scanf("%d%d", &op, &pos);
		if(op == 1) printf("%lld\n", v[pos]);
		else printf("%lld\n", tot[pos]);
	}
    system("pause");
    return 0;
}

总结

这场大部分都是数学题,我们一共AC了9题
其中我过了 \(L\)\(C\)
比赛体验总体挺好的,就是后期卡在了 \(B\)\(J\)

posted @ 2022-09-09 12:02  starlightlmy  阅读(99)  评论(0)    收藏  举报