2018 JUST Programming Contest 1.0 题解

题目链接  gym101778

Problem A

转化成绝对值之后算一下概率。这个题有点像 2018 ZOJ Monthly March Problem D ? 不过那个题要难一些~

#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;
const int N  = 2e5 + 10;


int T;
int n, m;
LL fac[N];

inline LL Pow(LL a, LL b, LL mod){
        LL ret(1);
        for (; b; b >>= 1, (a *= a) %= mod) if (b & 1) (ret *= a) %= mod;
        return ret;
}

inline LL C(LL n, LL m){ return m > n ? 0 : fac[n] * Pow(fac[m] * fac[n - m] % mod, mod - 2, mod) % mod; }


int main(){

	fac[0] = 1;
	rep(i, 1, 2e5 + 1) fac[i] = fac[i - 1] * 1ll * i % mod; 

	scanf("%d", &T);
	while (T--){
		scanf("%d%d", &n, &m);
		n = abs(n);

		if (n == 0 && m == 0){
			puts("1");
			continue;
		}
		
		if (m < n){
			puts("0");
			continue;
		}

		if ((m + n) % 2 == 1){
			puts("0");
			continue;
		}

		int x = (m + n) / 2;
		printf("%lld\n", C(m, x) * Pow(Pow(2, m, mod), mod - 2, mod) % mod);
	}

	return 0;
}

Problem B

把首项定成$1$然后二分答案就可以了

#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;

int T;
LL n, a, l, r, t;

int main(){

	scanf("%d", &T);
	while (T--){
		scanf("%lld%lld", &n, &a);

		l = 0, r = n;
		
		while (l + 1 < r){
			LL mid = (l + r) >> 1;
			if (mid * (mid + 1) / 2ll <= n * a - n + mid) l = mid;
			else r = mid - 1;
		}
		
		if (r * (r + 1) / 2ll <= n * a - n + r) t = r;
		else t = l;

		printf("%lld\n", t);
	}

	return 0;
}

Problem C

找规律。$ans = (n - 1) * phi(n)$

#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 = 1e6 + 10;

int T;
int phi[N];
int n;


int main(){

	rep(i, 2, 1e6 + 1){
		if (!phi[i]){
			for (int j = i; j <= 1e6; j += i){
				if (!phi[j]) phi[j] = j;
				phi[j] -= phi[j] / i;
			}
		}
	}

	scanf("%d", &T);
	while (T--){
		scanf("%d", &n);
		printf("%lld\n", 1ll * (n - 1) * phi[n]);
	}

	return 0;
}

Problem D

状态压缩,对于每一个集合求MST

#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)

const int N = 16;

int T;
int n, m, k;
int a[N][N], c[1 << N];
int all;
int ans;

int main(){

	scanf("%d", &T);
	while (T--){
		scanf("%d%d%d", &n, &m, &k);
		memset(c, 0, sizeof c);
		memset(a, -1, sizeof a);

		ans = 2e9;

		rep(i, 1, m){
			int x, y, z;
			scanf("%d%d%d", &x, &y, &z);
			--x;
			--y;
			a[x][y] = a[y][x] = z;
		}

		all = 0;
		rep(i, 1, k){
			int x;
			scanf("%d", &x);
			--x;
			all |= (1 << x);
		}

		int mx = (1 << n) - 1;
		rep(i, 1, mx){
			c[i] = 2e9;
			int p = 0;
			dec(j, n - 1, 0) if ((i >> j) & 1){
				p = j;
				break;
			}

			if ((i ^ (1 << p)) == 0){
				c[i] = 0;
				continue;
			}

			dec(j, n - 1, 0){
				if ((i >> j) & 1){
					rep(k, 0, n - 1){
						if (((i >> k) & 1) && (j != k) && (~a[j][k])) c[i] = min(c[i], c[i ^ (1 << j)] + a[j][k]);
					}
				}
			}
		}

		rep(i, 1, mx) if ((i & all) == all) ans = min(ans, c[i]);
		printf("%d\n", ans);
	}

	return 0;
}

Problem E

直接模拟

#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	fi		first
#define	se		second
#define	MP		make_pair

typedef long long LL;

int T;
int n, x, y;
int id, d, m;
int mxd, mxm;

int main(){

	scanf("%d", &T);

	while (T--){
		scanf("%d%d%d", &n, &x, &y);

		mxd = 1e9, mxm = 0;
		id = -1;
		rep(i, 1, n){
			scanf("%d%d", &d, &m);
			if (d <= x && m >= y){
				if (mxd > d || (mxd == d && mxm < m)){
					mxd = d;
					mxm = m;
					id  = i;
				}
			}
		}

		printf("%d\n", id);
	}

	return 0;

}

Problem F

这个题略卡常数。

对每个权值求二维前缀和,二分答案就好了。

#include <bits/stdc++.h>

namespace IO{
	const int MT = 20 * 1024 * 1024; 
	char IO_BUF[MT];
	int IO_PTR, IO_SZ;

	void begin(){
		IO_PTR = 0;
		IO_SZ = fread (IO_BUF, 1, MT, stdin);
	}
	template<typename T>
		inline bool scan_d (T & t){
			while (IO_PTR < IO_SZ && IO_BUF[IO_PTR] != '-' && (IO_BUF[IO_PTR] < '0' || IO_BUF[IO_PTR] > '9'))IO_PTR ++;
			if (IO_PTR >= IO_SZ) return false;
			bool sgn = false;
			if (IO_BUF[IO_PTR] == '-') sgn = true, IO_PTR ++;
			for (t = 0; IO_PTR < IO_SZ && '0' <= IO_BUF[IO_PTR] && IO_BUF[IO_PTR] <= '9'; IO_PTR ++)
				t = t * 10 + IO_BUF[IO_PTR] - '0';
			if (sgn) t = -t;
			return true;

		}
};

using namespace IO;
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 int M = 503;
const int N = 1e2 + 2;

int c[M][N][N];
int a[N][N];
int n, m, q;
int mx;
int T;


int calc(int x1, int y1, int x2, int y2, int val){
	return c[val][x2][y2] - c[val][x2][y1 - 1] - c[val][x1 - 1][y2] + c[val][x1 - 1][y1 - 1];
}

void print(int x){
	if (x > 9) print(x / 10);
	putchar(x % 10 + '0');
}

int main(){

	begin();
	scan_d(T);;
	while (T--){
		scan_d(n);
		scan_d(m);
		scan_d(q);

		mx = 0;

		rep(i, 1, n){
			rep(j, 1, m) scan_d(a[i][j]), mx = max(mx, a[i][j]);
		}

		rep(k, 0, mx){
			rep(i, 0, n + 1){
				rep(j, 0, m + 1) c[k][i][j] = 0;
			}
		}

		rep(k, 1, mx){
			rep(i, 1, n){
				rep(j, 1, m){
					c[k][i][j] = c[k][i - 1][j] + c[k][i][j - 1] - c[k][i - 1][j - 1] + (a[i][j] <= k);
				}
			}
		}


		while (q--){
			int x1, y1, x2, y2;
			scan_d(x1);
			scan_d(y1);
			scan_d(x2);
			scan_d(y2);

			int all = (x2 - x1 + 1) * (y2 - y1 + 1);
			all = (all + 1) / 2;

			int l = 1, r = mx;

			while (l + 1 < r){
				int mid = (l + r) >> 1;
				if (calc(x1, y1, x2, y2, mid) >= all) r = mid;
				else l = mid + 1;
			}

			int t;
			if (calc(x1, y1, x2, y2, l) >= all) t = l;
			else t = r;

			print(t);
			putchar(10);
		}
	}
	return 0;
}

Problem G

根据割线定理来做。

#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	fi		first
#define	se		second
#define	MP		make_pair

typedef long long LL;

int T;
int n, x, y;
int id, d, m;
int mxd, mxm;

int main(){

	scanf("%d", &T);

	while (T--){
		scanf("%d%d%d", &n, &x, &y);
		mxd = 1e9, mxm = 0;
		id = -1;
		rep(i, 1, n){
			scanf("%d%d", &d, &m);
			if (d <= x && m >= y){
				if (mxd > d || (mxd == d && mxm < m)){
					mxd = d;
					mxm = m;
					id  = i;
				}
			}
		}

		printf("%d\n", id);
	}

	return 0;

}

Problem H

假的数据结构……其实还是模拟

#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 int N = 1e5 + 10;

int T;
int n, m;
char s[N], ch[2];


int main(){

	scanf("%d", &T);
	while (T--){
		scanf("%d%d", &n, &m);
		scanf("%s", s + 1);

		int c = 0;
		rep(i, 1, (n + 1) >> 1) if (s[i] == s[n - i + 1]) ++c;
		int all = (n + 1) >> 1;
		
		int ans = 0;

		while (m--){
			int x;
			scanf("%d%s", &x, ch);
			if (s[x] == s[n - x + 1]){
				s[x] = ch[0];
				if (s[x] != s[n - x + 1]) --c;
			}

			else{
				s[x] = ch[0];
				if (s[x] == s[n - x + 1]) ++c;
			}

			if (c == all) ++ans;
		}

		printf("%d\n", ans);
	}

	return 0;
}

Problem I

签到

#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;

int T;


int main(){

	scanf("%d", &T);
	while (T--){
		int a, b, c, d;
		scanf("%d%d%d%d", &a, &b, &c, &d);

		if (a == d && b == c){
			puts("-1");
			continue;
		}

		if (a + c == b + d){
			if (c > a) puts("1"); else puts("2");
		}

		else if (a + c > b + d) puts("1");
		else puts("2");
	}

	return 0;
}

Problem J

挺有意思的一个题。

其实暴力做就可以了。因为在1e9的范围内质数间隔最大大概只有$320$。

#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;

int T;
int fg;
LL  l, r;

bool check(LL x){
	if (x <= 10) return false;
	string s1 = "";

	for (; x; x /= 10) s1 += x % 10 + '0';

	reverse(s1.begin(), s1.end());

	int n = s1.length();
	string s2 = s1.substr(0, (n + 1) / 2);
	string s3 = s1.substr((n + 1) / 2);

	LL a = 0, b = 0;

	for (auto u : s2) a = a * 10 + u - '0';
	for (auto u : s3) b = b * 10 + u - '0';

	return __gcd(a, b) == 1;
}

int main(){

	scanf("%d", &T);
	while (T--){
		scanf("%lld%lld", &l, &r);
		fg = 0;
		for (LL i = r; i >= l; --i){
			if (check(i)){
				fg = 1;
				printf("%lld\n", i);
				break;
			}
		}

		if (!fg) puts("-1");
	}

	return 0;

}

Problem K

模拟……

#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;
 
struct state{
	int x, y, z, t;
	state(){
		x = y = z = t = -1;
	}
	state(int x, int y, int z, int t) :
			x(x), y(y), z(z), t(t){
	}
	bool operator < (const state &e) const{
		return t < e.t;
	}
};
 
const int N = 1e2 + 2;


int T;
int n, m, k;
int fb[N];
int WA[N][N], FAC[N];
vector <state> sub;

 
int main(){
	
	scanf("%d", &T);
	while (T--){
		scanf("%d%d%d", &n, &m, &k);
		int x, y, z, tm, ts;
		sub.clear();
		rep(i, 0, k - 1){
			scanf("%d%d%d%d:%d", &x, &y, &z, &tm, &ts);
			sub.push_back(state(x - 1, y - 1, z, tm * 60 + ts));
		}
		sort(sub.begin(), sub.end());
		memset(fb, -1, sizeof fb);
		memset(WA, 0, sizeof WA);
		memset(FAC, 0, sizeof FAC);
		int ep = -1, sg = -1;
		pair<int, int> sp(-1, 0), rp(-1, 0);
		rep(i, 0, k - 1){
			if (sub[i].z == 0)
				++WA[sub[i].x][sub[i].y];
			else{
				if (fb[sub[i].x] == -1)
					fb[sub[i].x] = sub[i].y + 1;
				if (ep == -1)
					ep = sub[i].y + 1;
				sg = sub[i].y + 1;
				if (WA[sub[i].x][sub[i].y] == 0)
					++FAC[sub[i].y];
				if (FAC[sub[i].y] > sp.first || (FAC[sub[i].y] == sp.first && sub[i].y + 1 < sp.second))
					sp = make_pair(FAC[sub[i].y], sub[i].y + 1);
				if (WA[sub[i].x][sub[i].y] > rp.first || (WA[sub[i].x][sub[i].y] == rp.first && sub[i].y + 1 < rp.second))
					rp = make_pair(WA[sub[i].x][sub[i].y], sub[i].y + 1);
			}
		}
		rep(i, 0, n - 1) printf("%s%d", i ? " " : "", fb[i]);
		putchar(10);
		printf("%d %d %d %d\n", ep, sg, sp.se, rp.se);
	}
	return 0;
}

 

posted @ 2018-05-09 23:45  cxhscst2  阅读(345)  评论(0编辑  收藏  举报