[做题记录] 构造题选做

1. CF743C - Vladik and fractions (*1500)

目标:给定 \(n\),构造 \(x,y,z\) 满足 \(x \neq y, x \neq z, y \neq z\)\(\dfrac{2}{n}=\dfrac{1}{x}+\dfrac{1}{y}+\dfrac{1}{z}\)

Hint:\(\dfrac{1}{n}+\dfrac{1}{n+1}+\dfrac{1}{n(n+1)}=\dfrac{n+1+n+1}{n(n+1)}=\dfrac{2(n+1)}{n(n+1)}=\dfrac{2}{n}\)

\(n=1\) 时会出现 \(x=1,y=2,z=2\) 的情况,无解。

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
signed main () {
	int n;
	scanf ("%d", &n);
	if (n == 1) printf ("-1\n");
	else printf ("%d %d %d\n", n, n + 1, n * (n + 1));
	return 0;
}

2. CF1758D - Range = √Sum (*1800)

目标:给定 \(n\),求一个长度为 \(n\) 的数组 \([a_1,a_2,\dots,a_n]\),满足:\(1 \leq a_i \leq 10^9, 1 \leq i \leq n\)\(\displaystyle \max_{i=1}^{n}a_i-\min_{i=1}^{n}a_i=\sqrt{\sum_{i=1}^{n}a_i}\)

考虑奇偶分类。

\(n \bmod 2 = 0\) 时,发现 \(\displaystyle \left[\frac{n}{2},\frac{n}{2}+1,\dots,n-1,n+1,\dots,\frac{3n}{2}\right]\) 满足条件。

极差:\(\dfrac{3n-n}{2}=n\)

和:

\[\displaystyle \frac{\frac{3n}{2}(\frac{3n}{2}+1)}{2}-\frac{\frac{n}{2}(\frac{n}{2}-1)}{2}-n \]

\[\frac{\frac{9n^2}{4}+\frac{3n}{2}}{2}-\frac{\frac{n^2}{4}-\frac{n}{2}}{2}-n \]

\[\frac{9n^2}{8}+\frac{3n}{4}-\frac{n^2}{8}+\frac{n}{4}-n \]

\[Sum=n^2 \]

所以满足条件。

\(n \bmod 2 = 1\) 时,先构造一个以 \(n\) 为中心的公差为 \(1\) 的等差数列(\(\displaystyle \left[\frac{n+5}{2},\frac{n+7}{2},\dots,\frac{3n+3}{2}\right]\)),极差为 \(n-1\),和为 \(n^2\)

将所有数加 \(2\),可以让和变为 \(n^2+2n\),极差为 \(n-1\)

发现极差需要增加 \(2\),那就最小值减 \(1\),最大值加 \(1\) 吧,现在极差为 \(n+1\),和为 \(n^2+2n\),现在只需要将和加 \(1\) 了,那就将次大值加 \(1\),保证还会小于最大值,所以不会影响极差,和为 \(n^2+2n+1=(n+1)^2\)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
int _, n, a[300005];
signed main () {
	scanf ("%d", &_);
	while (_ --) {
		scanf ("%d", &n);
		if (n % 2 == 0) {
			for (int i = n / 2;i <= 3 * n / 2; ++ i) {
				if (i != n) printf ("%d ", i);
			}
			printf ("\n");
		}
		else {
			for (int i = 1;i <= n; ++ i) a[i] = i;
			int mid = n / 2 + 1;
			int delta = n - mid;
			for (int i = 1;i <= n; ++ i) a[i] += delta + 2;
			a[1] --, a[n] ++;
			a[n - 1] ++;
			for (int i = 1;i <= n; ++ i) printf ("%d ", a[i]);
			printf ("\n");
		}
	}
	return 0;
}

3. CF1734E - Rectangular Congruence (*2100)

目标:给定质数 \(n\),求一个矩阵满足:

  • 对于所有的 \(1 \leq i, j \leq n\)\(0 \leq a_{i,j} < n\)

  • 对于所有的 \(1 \leq r_1 < r_2 \leq n, 1 \leq c_1 < c_2 \leq n\),有 \((a_{r_1,c_1}+a_{r_2,c_2}) \bmod n \neq (a_{r_1,c_2}+a_{r_2,c_1}) \bmod n\)

  • 对于所有的 \(1 \leq i \leq n\)\(a_{i,i}=b_i\)

对第二个条件进行变形,有:\((a_{r_1,c_1}-a_{r_1,c_2})\bmod n=(a_{r_2,c_1}-a_{r_2,c_2}) \bmod n\)

所以对于一个合法的矩阵的同一行加上同一个数依然合法。

让第 \(i\) 行的差值为 \(i-1\) 的倍数,可以构造出:

\(\begin{bmatrix}0&0&\dots&0\\1&2&\dots&n-1\\\vdots&\vdots&\ddots&\vdots\\0&(n-1)&\dots&(n-1)\times(n-1)\bmod n\end{bmatrix}\)

剩下的操作就是调整每一行使得它满足第三个条件。

第一个条件就是 \(\bmod n\)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
//#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
int a[355][355], n, b[355];
signed main () {
	scanf ("%d", &n);
	for (int i = 1;i <= n; ++ i) {
		for (int j = 1;j <= n; ++ j) {
			a[i][j] = (i - 1) * (j - 1) % n;
		}
	}
	for (int i = 1;i <= n; ++ i) {
		scanf ("%d", &b[i]);
		int delta = b[i] - a[i][i];
		for (int j = 1;j <= n; ++ j) a[i][j] += delta;
	}
	for (int i = 1;i <= n; ++ i) {
		for (int j = 1;j <= n; ++ j) {
			a[i][j] = (a[i][j] % n + n) % n;
			printf ("%d ", a[i][j]);
		}
		printf ("\n");
	}
	return 0;
}
posted @ 2023-03-29 20:26  CountingGroup  阅读(11)  评论(0编辑  收藏  举报