码迷,mamicode.com
首页 > 其他好文 > 详细

2017 ACM/ICPC 广西邀请赛 题解

时间:2017-09-01 22:12:14      阅读:378      评论:0      收藏:0      [点我收藏+]

标签:col   define   等于   线段   line   ems   while   return   unit   

题目链接  Problems

HDOJ上的题目顺序可能和现场比赛的题目顺序不一样,

我这里的是按照HDOJ的题目顺序来写的。

Problem 1001

签到

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)

typedef long long LL;

LL n, f[31];
int ans;


int main(){

	f[1] = 1LL;
	for (LL i = 2; i <= 15; ++i){
		f[i] = 1LL;
		rep(j, 1, i) f[i] *= i;
	}

	while (~scanf("%lld", &n)){
		ans = 0;
		rep(i, 1, 15) if (f[i] <= n) ans = max(ans, i);
		printf("%d\n", ans);
	}	


	return 0;
}

 

 

Problem 1002

这道题的话,其实一个点上是可以有多种颜色的

因为最多只有51种颜色,所以我们维护51棵线段树即可。

我们对y坐标建立线段树,对于每个y,我们只需要最小的x在哪里即可。

因为他的询问的x坐标下界总是1,那么我们只要看看y1到y2的最小值是否小于等于给定的x即可。

询问的时候做51次子询问就可以了。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

typedef long long LL;

const int N = 2e6 + 10;

int X, c, d, x, y, op, ans, ret, cnt;
int root[53];
int l[N], r[N], v[N];

void update(int &i, int L, int R, int x, int val){
	if (i == 0){
		i = ++cnt;
		v[i] = val;
	}

	v[i] = min(v[i], val);
	if (L == R) return;

	int mid = (L + R) >> 1;
	if (x <= mid) update(l[i], L, mid, x, val);
	else update(r[i], mid + 1, R, x, val);
}

void query(int i, int L, int R){
	if (ret || i == 0) return;
	if (c <= L && R <= d){
		if (v[i] <= X) ret = 1;
		return;
	}

	int mid = (L + R) >> 1;
	if (c <= mid) query(l[i], L, mid);
	if (d >  mid) query(r[i], mid + 1, R);
}	

int main(){

	while (true){
		scanf("%d", &op);
		if (op == 3) break;
		if (op == 0){
			rep(i, 1, cnt) l[i] = r[i] = 0;
			memset(root, 0, sizeof root);
			cnt = 0;
		}

		if (op == 1){
			scanf("%d%d%d", &x, &y, &c);
			update(root[c], 1, 1000000, y, x);
		}

		if (op == 2){
			scanf("%d%d%d", &X, &c, &d);
			ans = 0;
			rep(i, 0, 50){
				ret = 0;
				query(root[i], 1, 1000000);
				ans += ret;
			}
			printf("%d\n", ans);
		}
	}


	return 0;
}

 

 

 

 

Problem 1003

我们对于每一条边,找到所有包含这条边的三元环,个数计为x

然后这对答案的贡献就是$C_{x}^{2}$

判断两点之间是否有边的时候要手写哈希才能过

#include <bits/stdc++.h>

const int N = 2e5 + 10;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

namespace Hashmap{
	const int P = 1000007, seed = 2333;
	int u[N << 2], v[N << 2], nt[N << 2];
	int head[P], inum;
	inline void init(){
		inum = 0;
		memset(u, 0, sizeof u);
		memset(v, 0, sizeof v);
		memset(nt, 0, sizeof nt);
		memset(head, 0, sizeof head);
	}

	inline void add(int _u, int _v){
		int t = (_u * seed + _v) % P;
		u[++inum] = _u, v[inum] = _v, nt[inum] = head[t], head[t] = inum;
	}

	inline bool query(int _u, int _v){
		int t = (_u * seed + _v) % P;
		for (int p = head[t]; p; p = nt[p])
			if (u[p] == _u && v[p] == _v) return 1;
		return 0;
	}
}

using namespace std;
using namespace Hashmap;

typedef long long LL;

vector<int> a[N];

struct ss{ int x, y; } e[N];

int n, m;

int main(){

	while (~scanf("%d%d",&n, &m)){
		init();
		rep(i, 1, n) a[i].clear();
		rep(i, 1, m){
			int x, y;
			scanf("%d%d", &x, &y);
			e[i].x = x;
			e[i].y = y;
			a[x].push_back(y);
			a[y].push_back(x);
			add(x, y);
			add(y, x);
		}

		LL ans = 0;
		rep(i, 1, m){
			int x = e[i].x, y = e[i].y;
			if (a[e[i].y].size() < a[e[i].x].size()) swap(x, y);
			LL tot = 0;
			for (auto u: a[x]) if (query(u, y))  tot++;
			ans += tot * (tot - 1) / 2;
		}

		printf("%lld\n", ans);
	}
	return 0;
}

 

 

Problem 1004

这题规律找了半天……

$f[n] = f[n - 1] + 5f[n - 2] + f[n - 3] - f[n - 4]$

然后矩阵加速下就可以了

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second


typedef long long LL;

const LL mod = 1e9 + 7;

struct Matrix{
	LL arr[6][6];
} f, unit, a;


LL m, k;
int n;

Matrix Add(Matrix a, Matrix b){
	Matrix c;
	rep(i, 1, n) rep(j, 1, n){
		c.arr[i][j] = (a.arr[i][j] + b.arr[i][j]) % mod;
	}
	return c;
}

Matrix Mul(Matrix a, Matrix b){
	Matrix c;
	rep(i, 1, n) rep(j, 1, n){
		c.arr[i][j] = 0;
		rep(k, 1, n) (c.arr[i][j] += (a.arr[i][k] * b.arr[k][j] % mod)) %= mod;
	}
	return c;
}

Matrix Pow(Matrix a, LL k){
	Matrix ret(unit); for (; k; k >>= 1, a = Mul(a, a)) if (k & 1) ret = Mul(ret, a); return ret;
}


int main(){

	n = 4;

	memset(f.arr, 0, sizeof f.arr);
	memset(a.arr, 0, sizeof a.arr);
	memset(unit.arr, 0, sizeof unit.arr);

	rep(i, 1, n) unit.arr[i][i] = 1;
	f.arr[1][1] = 1;
	f.arr[1][2] = 5;
	f.arr[1][3] = 1;
	f.arr[1][4] = 1000000006;
	f.arr[2][1] = 1;
	f.arr[3][2] = 1;
	f.arr[4][3] = 1;
	
	a.arr[1][1] = 36;
	a.arr[2][1] = 11;
	a.arr[3][1] = 5;
	a.arr[4][1] = 1;

	while (~scanf("%lld", &m)){
		if (m == 1LL){ puts("1");  continue;}
		if (m == 2LL){ puts("5");  continue;}
		if (m == 3LL){ puts("11"); continue;}
		if (m == 4LL){ puts("36"); continue;}
		if (m == 5LL){ puts("95"); continue;}

		k = m - 4;

		Matrix b = Pow(f, k);
		Matrix c = Mul(b, a);
		printf("%lld\n", c.arr[1][1]);		
	}

	return 0;
}

 

 

Problem 1005

Problem 1006

Problem 1007

Problem 1008

Problem 1009

Problem 1010

Problem 1011

Problem 1012

 

2017 ACM/ICPC 广西邀请赛 题解

标签:col   define   等于   线段   line   ems   while   return   unit   

原文地址:http://www.cnblogs.com/cxhscst2/p/7465136.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!