构造死磕
什么是构造
小学中学奥数- 先用数学解决再编程实现的构造题
- 一般算法无法解决
- (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 imes (x-1)} - dfrac{x-1}{x imes (x-1)}= dfrac{1}{x imes ( x-1)}
]
- 那么我们就有了$$frac{1}{x} = frac{1}{x-1}+frac{1}{x imes (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 imes N (k in N)),这显然是不可能的,因为只有(1)满足这个条件.
- 那么我们可以让序列来回震荡么?
- 考虑前缀和为(0,1,-1,2,-2,3,-3,cdots),我们想想是否可以构造.
- 第一项为(N),第二项为(1),第三项为(N-2),第四项为(3),第五项为(N-4) (cdotscdots)
- 显然可以构造,只要满足(N)偶数即可!
- (N)为奇数时是否可以构造呢? (N=1)时显然可以,之后的(N=3,5,7cdots)时,
根据官方题解:(sum^{N}_{i=1}{i} = frac{N imes(N-1)}{2})而(Nmidfrac{N imes(N-1)}{2}).故无解.
task2
- 我们同样发现,(N)出现后的前缀积全为(0),所以(N)必须在最后一位出现,同理(1)出现前一位的前缀积和自己这一项的前缀积相等,所以(1)必须出现在第一项.
- 然后考虑如何构造,先考虑递增的.
- 第一项为(1),我们是否能构造出第(k,k ot = 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),那么(Nmid (N-1)!)是一定的,对于(4),其因子在(3!)只出现一次,成立.
- 特判一下(1)和(4),这一题也做完了.