题目大意:
长度为 n ( ≤ 1 0 6 ) n(\le 10^6) n(≤106)的全排列,有多少种排列,满足 ∀ i ∈ [ 1 , n ] , p i % p i + 1 ≤ 2 , ( p n + 1 = p 1 ) \forall i \in [1,n],\,p_i\%p_{i+1}\le2,\,(p_{n+1}=p_1) ∀i∈[1,n],pi%pi+1≤2,(pn+1=p1)
解题思路:
-
首先可以发现有两个特别的数:1,2,不管这两个数两侧是什么数都符合上面的条件,而且上面的条件: p i % p i + 1 ≤ 2 p_i\%p_{i+1}\le2 pi%pi+1≤2还包含了一个条件: p i > p i + 1 p_i > p_{i+1} pi>pi+1
-
那么题目就有一个等价的问题:序列 { n , n − 1 , n − 2 , . . . , 3 } \{n,n-1,n-2,...,3\} {n,n−1,n−2,...,3},有多少种子序列的选法,使得选择的子序列以及未选择的子序列都满足相邻取模小于等于2
-
那么每个数有两种放法,然后最后还要 O ( n ) O(n) O(n)遍历检查是否合法,复杂度为 O ( 2 n ⋅ n ) O(2^n\cdot n) O(2n⋅n),这样的复杂度显然是不能接受的
-
其实发现当前的放法仅仅只跟两个序列结尾的数有关,那么 d p dp dp方程为:
先 设 f [ i ] [ j ] 为 第 一 个 序 列 结 尾 为 i , 另 一 个 为 j 当 前 n ∼ x 都 已 经 放 在 两 个 序 列 中 , 且 合 法 , 那 么 一 定 存 在 一 个 序 列 结 尾 为 x , 设 另 一 个 为 i ( i > x ) 当 前 放 的 是 x − 1 , 所 以 有 f [ x − 1 ] [ i ] + = f [ x ] [ i ] 如 果 ( i % ( x − 1 ) ) ≤ 2 , 则 有 f [ x ] [ x − 1 ] + = f [ x ] [ i ] ↔ f [ x − 1 ] [ x ] + = f [ x ] [ i ] , ( i % ( x − 1 ) ≤ 2 ) \\先设f[i][j]为第一个序列结尾为i,另一个为j 当前n\sim x都已经放在两个序列中,且合法,那么一定存在一个序列结尾为x,设另一个为i(i>x) \\ 当前放的是x-1,所以有f[x-1][i]+=f[x][i] \\ 如果(i\%(x-1))\le2,则有f[x][x-1]+=f[x][i] \leftrightarrow f[x-1][x]+=f[x][i],(i\%(x-1)\le2) \\ 先设f[i][j]为第一个序列结尾为i,另一个为j当前n∼x都已经放在两个序列中,且合法,那么一定存在一个序列结尾为x,设另一个为i(i>x)当前放的是x−1,所以有f[x−1][i]+=f[x][i]如果(i%(x−1))≤2,则有f[x][x−1]+=f[x][i]↔f[x−1][x]+=f[x][i],(i%(x−1)≤2) -
对于这个复杂度也是 O ( n 2 ) O(n^2) O(n2),虽然比之前优秀,但仍然不能接受,我们可以把这里的转移看作如下的表:
… | x x x | x + 1 x+1 x+1 | x + 2 x+2 x+2 | … | |
---|---|---|---|---|---|
x x x | 无 | 无 | f [ x ] [ x + 1 ] f[x][x+1] f[x][x+1] | f [ x ] [ x + 2 ] f[x][x+2] f[x][x+2] | … |
x − 1 x-1 x−1 | 无 | f [ x − 1 ] [ x ] = ∑ i % ( x − 1 ) ≤ 2 f [ x ] [ i ] f[x-1][x]=\sum_{i\%(x-1)\le2}f[x][i] f[x−1][x]=∑i%(x−1)≤2f[x][i] | f [ x − 1 ] [ x + 1 ] = f [ x ] [ x + 1 ] f[x-1][x+1]=f[x][x+1] f[x−1][x+1]=f[x][x+1] | f [ x − 1 ] [ x + 2 ] = f [ x ] [ x + 2 ] f[x-1][x+2]=f[x][x+2] f[x−1][x+2]=f[x][x+2] | … |
- 所以第一维实际上是可以不要的,而 i % ( x − 1 ) ≤ 2 i\%(x-1)\le2 i%(x−1)≤2的 i i i可以通过筛法直接得到,最终时间复杂度是 O ( n l n ( n ) ) O(nln(n)) O(nln(n))
- 而我们最终计算出的 d p [ 4 ] , d p [ 5 ] , . . . , d p [ n ] dp[4],dp[5],...,dp[n] dp[4],dp[5],...,dp[n]其实就相当于 f [ 3 ] [ 4 ] , f [ 3 ] [ 5 ] , . . . , f [ 3 ] [ n ] f[3][4],f[3][5],...,f[3][n] f[3][4],f[3][5],...,f[3][n]
- 所以最终答案就是 ( d p [ 4 ] + . . . + d p [ n ] + 1 ) ∗ 2 (dp[4]+...+dp[n]+1)*2 (dp[4]+...+dp[n]+1)∗2,加1是因为,还有可能某个序列不放,乘2是因为1不一定要在第一个序列中,它可以和2互换
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
vector<int> d[N];
int dp[N];
void add(int &x, int y) {
x += y;
if (x >= mod) x -= mod;
else if (x < 0) x += mod;
}
int n;
int main() {
cin >> n;
if (n <= 2) {
cout << n << endl;
return 0;
}
dp[n] = 1;
for (int i = n - 1; i >= 4; i--) {
dp[i] = 1;
int x = i - 1;
for (int k = x; k <= n; k += x) {
for (int j = 0; j <= 2; j++)
if (k + j > i) add(dp[i], dp[k + j]);
}
}
int ans = 1;
for (int i = 4; i <= n; i++) add(ans, dp[i]);
cout << 1ll * ans * 2 * n % mod << endl;
}