ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AtCoder Regular Contest 118 VP 记录

2022-05-04 08:00:25  阅读:172  来源: 互联网

标签:AtCoder le frac Contest int long VP 100 define


目录

赛时 1h 才过一题,最后过了三题倒还好。

A - Tax Included Price

给定 \(t,n\),让所有正整数 \(i\) 变为 \(\left\lfloor\frac{100+t}{100} \times i \right \rfloor\) ,问第 \(n\) 个没出现的正整数是什么。

考虑什么时候会多 \(1\)。

因为 \(\frac{100+t}{100} \times i = i + \frac{ti}{100}\) ,所以当 \(ti\ge100\) 的时候会有第一个正整数没出现,所以第 \(n\) 个就是:

设 \(p\) 是满足 \(tp \ge 100n\) 的最小的 \(p\),那么答案就是 \(p + \frac{tp}{100}-1\)。

signed main() {
//	Check();
	int t = read(), n = read();
	int p = 100 * n / t + (100 * n % t > 0);
	printf("%lld\n", p + t * p / 100 - 1);
	return 0;
}

B - Village of M People

给你一个长度为 \(K\) 的序列 \(a\),且 \(\sum_i a_i = n\) ,你需要填一个序列 \(b\),需要满足 \(\sum_i b_i = m\),要使得 \(\max_i |\frac{b_i}{m} - \frac{a_i}{n}|\) 的最小。

直接二分,然后算贡献即可。

需要注意的是,这个东西要先让 \(|\frac{b_i}{m} - \frac{a_i}{n}|\ge - mid\),如果连着都不满足也是不合法的。

然后看看能不能把剩下的 \(x\) 分配到 \(b\) 里使得 \(|\frac{b_i}{m} - \frac{a_i}{n}| \le mid\)。

虽然看上去比较麻烦,但它也有可二分性。

#include<bits/stdc++.h>
#define LL long long 
#define int long long
#define orz cout << "tyy YYDS!!!\n"
using namespace std;
const int MAXN = 2e5 + 10;
const int INF = 1e18 + 7;
const int mod = 998244353;

int read() {
	int s = 0, f = 0; char ch = getchar();
	while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
	while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

int K, n, m;
int a[MAXN];
int cnt[MAXN];
int b[MAXN];

bool Check(int lim) {
	int res = 0;
	for(int i = 1; i <= K; ++i) b[i] = - m * a[i], cnt[i] = 0;
	for(int i = 1; i <= K; ++i) {
		if(b[i] < - lim) {
			int tmp = (- lim - b[i] - 1) / n + 1;
			b[i] += tmp * n;
			res += tmp, cnt[i] += tmp;
		}
	}
	if(res > m) return false;
	for(int i = 1; i <= K; ++i) {
		if(b[i] < lim) {
			int tmp = min(m - res, (int)(lim - b[i]) / n);
			res += tmp, cnt[i] += tmp, b[i] += n * tmp;
		}
	}
	return res >= m;
}

signed main() {
	K = read(), n = read(), m = read();
	for(int i = 1; i <= K; ++i) a[i] = read();
	int l = INF, r = - INF;
	for(int i = 1; i <= K; ++i) {
		l = min(l, - m * a[i]);
		r = max(r, n * m - m * a[i]);
	}
	r = max(-l, r), l = 0;
	int ans = l;
	while(l <= r) {
		int mid = (l + r) / 2;
		if(Check(mid)) ans = mid, r = mid - 1;
		else l = mid + 1;
	}
	Check(ans);
	for(int i = 1; i <= K; ++i) printf("%lld ", cnt[i]);
	return 0;
}

C - Coprime Set

构造一个长度为 \(n\) 的序列 \(a\),满足下面条件:

  • \(1 \le a_i \le 10000\);
  • 任意两个位置不同,任意两个位置的 \(\gcd > 1\)。
  • 整个序列的 \(\gcd =1\)。

\(3 \le n \le 2500\)。

考虑 \(n=3\) 的时候,肯定是选三个质因子,然后一个数拿两个。

考虑 \(n >3\) 的时候,肯定也是拿两个质因子,然后再带一个其他的倍数,其他的倍数直接枚举即可。

那么三个质因子我们选 \(2,3,5\),那么剩下的数都让他们是 \(2 \times 3\) 或者 \(3 \times 5\) 或者 \(2 \times 5\) 倍数就行。

发现在 \(15 < x \le 2500\) 的数中,这样的数有 \(2662\) 个,够用了。

#include<bits/stdc++.h>
#define LL long long 
//#define int long long
#define orz cout << "tyy YYDS!!!\n"
using namespace std;
const int MAXN = 2e5 + 10;
const int INF = 1e9 + 7;
const int mod = 998244353;

int read() {
	int s = 0, f = 0; char ch = getchar();
	while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
	while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

int n;
int a[MAXN], stc[MAXN], sc = 0;
int prim[MAXN], Cnt = 0;
bool vis[MAXN];

void Init(int M) {
	for(int i = 2; i <= M; ++i) {
		if(!vis[i]) prim[++Cnt] = i;
		for(int j = 1; j <= Cnt && i * prim[j] <= M; ++j) {
			vis[i * prim[j]] = true;
			if(i % prim[j] == 0) break;
		}
	}
}

signed main() {
	Init(3333);
	int p = 0;
	for(int i = 16; i <= 10000; ++i) 
		if(i % 6 == 0 || i % 10 == 0 || i % 15 == 0) 
			stc[++sc] = i;
	n = read();
	a[1] = 2 * 3, a[2] = 3 * 5, a[3] = 2 * 5;
	for(int i = 4; i <= n; ++i) a[i] = stc[sc--];
	for(int i = 1; i <= n; ++i) cout << a[i] << " "; puts("");
	return 0;
}

D - Hamiltonian Cycle

给一个 \(P\),构造一个长度为 \(P\) 的序列 \(a\),\(a_1 = a_P = 1\) ,\(a[1\sim P-1]\) 是 \(P-1\) 的排列。

并且相邻两个数满足下面的四个条件之一:

  • \(a_i \equiv x a_{i-1} \pmod P\)
  • $ a_{i-1} \equiv x a_{i} \pmod P$
  • \(a_i \equiv y a_{i-1} \pmod P\)
  • \(a_{i-1} \equiv y a_{i} \pmod P\)

\(P,x,y\) 给定。

\(2 \le P \le 10^5\)。

根据题目来看怎么都像是哈密尔顿回路好吧。

但是你根据题目的规则建一个图出来也不能在一个多项式复杂度内找到一个长度为 \(n\) 的环。

所以应该找一些特殊性质。

我们考虑构建一个平面图

设 \(n\) 是最小的 \(a^n \equiv 1 \pmod P\)。

把 \(a^i, 0 \le i < n\) 加入一个集合 \(S\),设 \(m\) 是最小的 \(b^i \bmod P \in S\)。

那么我们能构建出一个 \(n\) 行 \(m\) 列的平面图。

第 \(i\) 行第 \(j\) 列表示的是 \(a^i b^j\),不难发现,从一个位置向四周哪里走都是可以的。

如果 \(n \times m = P-1\) 则有解,否则交换 \(x,y\) 再这样判断一遍,如果依旧不行那么就无解。

如果有解的话

问题就转化成了从左上角开始走一个哈密尔顿回路。

针对 \(n,m\) 的奇偶性分别构造一个对应的路径即可。

#include<bits/stdc++.h>
#define LL long long 
#define int long long
#define orz cout << "tyy YYDS!!!\n"
using namespace std;
const int MAXN = 2e5 + 10;
const int INF = 1e9 + 7;
const int mod = 998244353;

int n, a, b;
int N, M;
vector<int> c[MAXN];
bool vis[MAXN];

int read() {
	int s = 0, f = 0; char ch = getchar();
	while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
	while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

bool Check(int a, int b) {
	memset(vis, false, sizeof vis);
	for(int i = 1, x = 1; i < n; ++i) {
		vis[x] = true;
		x = x * a % n;
		if(x == 1) { N = i; break; }
	}
	for(int i = 1, x = 1; i < n; ++i) {
		x = x * b % n;
		if(vis[x]) { M = i; break; }
	}
	return N * M == n - 1;
}

signed main() {
	n = read(), a = read(), b = read();
	if(n == 2) return puts("Yes"), puts("1 1"), 0;
	if(!Check(a, b)) return puts("No"), 0;
	swap(a, b);
	if(!Check(a, b)) return puts("No"), 0;
	puts("Yes");
	for(int i = 0, x = 1; i < N; ++i, x = x * a % n) 
		for(int j = 0, p = x; j < M; ++j, p = p * b % n) 
			c[i].push_back(p);
	if(N == 1) {
		for(auto v : c[0]) printf("%lld ", v);
		puts("1");
	} else if(M == 1) {
		for(int i = 0; i < N; ++i) printf("%lld ", c[i][0]);
		puts("1");
	} else if(M % 2 == 0 || N % 2 == 1) {
		for(int i = 0; i < M; ++i) printf("%lld ", c[0][i]); puts("");
		for(int i = M - 1, v = 1; i >= 0; --i, v ^= 1) {
			if(v == 1) {
				for(int j = 1; j < N; ++j) printf("%lld ", c[j][i]);
			} else {
				for(int j = N - 1; j >= 1; --j) printf("%lld ", c[j][i]);
			}
		}
		puts("1");
	} else if(M % 2 == 1) {
		for(int i = 0, v = 1; i < N; ++i, v ^= 1) {
			if(v) {
				for(int j = 0; j < M; ++j) cout << c[i][j] << " ";
			} else {
				for(int j = M - 1; j >= 0; --j) cout << c[i][j] << " ";
			}
		}
		puts("1");
	}
	return 0;
} 

标签:AtCoder,le,frac,Contest,int,long,VP,100,define
来源: https://www.cnblogs.com/Silymtics/p/VPARC118.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有