构造入门
构造死磕
什么是构造
小学中学奥数- 先用数学解决再编程实现的构造题
- 一般算法无法解决
- \(NOI+\)难度\(PJ-\)代码量
- 坑
构造举例
CF743C Vladik and fractions
- 题目让我们构造一组数字,满足\(\frac{2}{n} = \frac{1}{x} + \frac{1}{y} + \frac{1}{z}\)
第一眼看到就想到听老师讲了半天才知道这不是简单的OI题目,而是先用数学解决再编程实现的构造题- 我们考虑如何构造:
\[\dfrac{2}{n} = \dfrac{1}{x} + \dfrac{1}{y} + \dfrac{1}{z}
\]
- 首先容易想到\(\frac{2}{n} = \frac{1}{n} + \frac{1}{n}\)
- 这样我们可以令\(x = n\),对原式化简可以推出\(\frac{1}{n} = \frac{1}{y} + \frac{1}{z}\)
- 我们考虑
人人都要在推数列时用到的一个公式:
\[\dfrac{1}{x} - \dfrac{1}{x-1} = \dfrac{x}{x \times (x-1)} - \dfrac{x-1}{x \times (x-1)}= \dfrac{1}{x \times ( x-1)}
\]
- 那么我们就有了$$\frac{1}{x} = \frac{1}{x-1}+\frac{1}{x \times (x - 1)}$$
- 把上式中的\(x\)替换成\(n\)这一题就出来了.
#include <iostream>
using namespace std;
int N;
int main()
{
cin >> N;
if(N == 1){
cout << -1 << endl;
return 0;
}
else {
cout << N <<' '<< N+1 <<' '<< N*(N+1);
}
return 0;
}
P3599 Koishi Loves Construction
- 这一题就是个坑,虽然大多数构造都是坑,但是您就不能给一组std的结果么?
task1
- 我们先考虑\(task1\),要求求出一组\(1-N\)排列使得其前缀和在\(\% N\)意义下各不相同.
- 我们发现排列中\(N\)前一项和自己这一项的前缀和相等,所以\(N\)只能处于排列首位
- 我们考虑取模的性质,对数字加上或者减去\(N\)并不影响答案.
- 那么第一项为\(N\),其前缀和取模后为\(0\).我们是否能构造出前缀和依次递增\(1\)的序列呢?
- 想了想好像不行,因为如果想依次递增\(1\),那么每一项都为\(1 + k \times N\ (k \in\ N)\),这显然是不可能的,因为只有\(1\)满足这个条件.
- 那么我们可以让序列来回震荡么?
- 考虑前缀和为\(0,1,-1,2,-2,3,-3,\cdots\),我们想想是否可以构造.
- 第一项为\(N\),第二项为\(1\),第三项为\(N-2\),第四项为\(3\),第五项为\(N-4\) \(\cdots\cdots\)
- 显然可以构造,只要满足\(N\)偶数即可!
- \(N\)为奇数时是否可以构造呢? \(N=1\)时显然可以,之后的\(N=3,5,7\cdots\)时,
根据官方题解:\(\sum^{N}_{i=1}{i} = \frac{N\times(N-1)}{2}\)而\(N\mid\frac{N\times(N-1)}{2}\).故无解.
task2
- 我们同样发现,\(N\)出现后的前缀积全为\(0\),所以\(N\)必须在最后一位出现,同理\(1\)出现前一位的前缀积和自己这一项的前缀积相等,所以\(1\)必须出现在第一项.
- 然后考虑如何构造,先考虑递增的.
- 第一项为\(1\),我们是否能构造出第\(k,k\not = N\)项前缀积为\(k\)呢?
- 那么,每一项应该为\(1,\frac{2}{1},\frac{3}{2},\frac{4}{3},\cdots\),考虑\(x \cdot inv(x)\equiv1(mod\ N)\),我们可以有如下转化\(\frac{k}{k-1} = k \cdot inv(k-1)\),然后坑比样例不是这样给的,但是这样是对的.
- 思考下什么时候无法构造,如果\(N\)不为质数和\(4\),那么\(N\mid (N-1)!\)是一定的,对于\(4\),其因子在\(3!\)只出现一次,成立.
- 特判一下\(1\)和\(4\),这一题也做完了.