题目来源:
大致题意:
输入n
从1到n 共n个数 在所有的排列中 任意两个连续的数字不相邻的排列有多少种
例如:
输入n等于4时 输出2 有两种
分别是3 1 4 2和2 4 1 3 都是满足要求的合法排列
其他排列都不符合要求 例如1 4 2 3中2和3连续 不合法
解法1:O(N)的一维DP
用n表示输入 用f【n】表示对应的输出
1-5的f【n】用DFS暴力跑 之后的DP
状态转移方程:
f[i] = (i + 1) * f[i - 1] - (i - 2) * f[i - 2] - (i - 5) * f[i - 3] + (i - 3) * f[i - 4];
f【n】即为答案
解法2:O(N*N)的二维DP
f[0/1][i][j]:0/1表示i和i-1这两个数是否连续 i表示1到i i个数的情况 j表示在i个数中有j对数连续的情况
即,i和i-1 不连续/连续 一共i个数 其中有j对数连续的方案数是f【0/1】【i】【j】
i为1-5的所有情况DFS暴力跑 之后二维DP
状态转移方程:
f[0][i][j] = f[0][i - 1][j + 1] * (j + 1) + f[1][i - 1][j + 1] * j + f[0][i - 1][j] * (i - j - 2) + f[1][i - 1][j] * (i - j - 1);
f[1][i][j] = f[1][i - 1][j - 1] + f[1][i - 1][j] + f[0][i - 1][j - 1] * 2;
f【0】【n】【0】即为答案
UPD1:
解法2可以把f[0][1][0]设为1 其他设为0 直接从2开始遍历DP 不需要DFS跑前几个
AC代码1:
// #define NDEBUG
#include <bits/stdc++.h>
using namespace std;
namespace AIN
{
using db = double;
using ll = long long;
#define edl '\n'
#define str string
#define pll pair<ll, ll>
#define fir first
#define sec second
#define heap priority_queue
#define SPO(n) fixed << setprecision(n)
#define FOR(i, l, r) for (auto i = l; i <= (r); ++i)
#define ROF(i, r, l) for (auto i = r; i >= (l); --i)
#ifdef debugcmd
#define DBG(n) cout << "!!! " << #n << ": " << n << edl
#else
#define DBG(n) ;
#endif
template <typename T>
T KSM(T base, long long exp)
{
// assert(exp >= 0);
T res = 1;
while (exp)
{
if (exp & 1)
res *= base;
base *= base;
exp >>= 1;
}
return res;
}
long long __lcm(long long lhs, long long rhs) { return lhs / __gcd(lhs, rhs) * rhs; }
// constexpr db PI = acos(-1.0);
// constexpr db EPS = 1.0e-9;
constexpr long long LNF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int INF = 0x3f3f3f3f;
// constexpr long long MOD = 998244353;
// constexpr long long MOD = 1e9 + 7;
constexpr long long MOD = 7777777;
constexpr int MXN = 1e5 + 5;
}
using namespace AIN;
template <long long P>
struct ModInt
{
public:
ModInt() : _v(0) {}
template <typename T>
ModInt(T v) { _v = ((long long)v % P + P) % P; }
long long val() const { return _v; }
ModInt &operator++()
{
++_v;
if (_v == P)
_v = 0;
return *this;
}
ModInt &operator--()
{
if (_v == 0)
_v = P;
--_v;
return *this;
}
ModInt operator++(int)
{
ModInt oldVal = *this;
++*this;
return oldVal;
}
ModInt operator--(int)
{
ModInt oldVal = *this;
--*this;
return oldVal;
}
ModInt &operator+=(const ModInt &rhs)
{
_v += rhs._v;
_v %= P;
return *this;
}
ModInt &operator-=(const ModInt &rhs)
{
_v -= rhs._v;
_v = (_v + P) % P;
return *this;
}
ModInt &operator*=(const ModInt &rhs)
{
_v *= rhs._v;
_v %= P;
return *this;
}
ModInt &operator/=(const ModInt &rhs) { return *this = *this * rhs.inv(); }
ModInt operator+() const { return *this; }
ModInt operator-() const { return ModInt() - *this; }
ModInt pow(long long exp) const
{
// assert(exp>=0);
ModInt res = 1;
ModInt base = *this;
while (exp)
{
if (exp & 1)
res *= base;
base *= base;
exp >>= 1;
}
return res;
}
ModInt inv() const
{
// assert(_v);
return pow(P - 2);
}
friend ModInt operator+(const ModInt &lhs, const ModInt &rhs)
{
ModInt res = lhs;
res += rhs;
return res;
}
friend ModInt operator-(const ModInt &lhs, const ModInt &rhs)
{
ModInt res = lhs;
res -= rhs;
return res;
}
friend ModInt operator*(const ModInt &lhs, const ModInt &rhs)
{
ModInt res = lhs;
res *= rhs;
return res;
}
friend ModInt operator/(const ModInt &lhs, const ModInt &rhs)
{
ModInt res = lhs;
res /= rhs;
return res;
}
friend bool operator==(const ModInt &lhs, const ModInt &rhs) { return lhs._v == rhs._v; }
friend bool operator!=(const ModInt &lhs, const ModInt &rhs) { return lhs._v != rhs._v; }
friend std::istream &operator>>(std::istream &is, ModInt &aim)
{
long long tmp;
is >> tmp;
aim = ModInt(tmp);
return is;
}
friend std::ostream &operator<<(std::ostream &os, const ModInt &aim) { return os << aim.val(); }
private:
long long _v;
};
using mint = ModInt<MOD>;
ll n;
mint f[MXN];
void Init(void)
{
f[1] = 1;
f[2] = 0;
f[3] = 0;
f[4] = 2;
f[5] = 14;
FOR(i, 6, 1e3 + 5)
f[i] = (i + 1) * f[i - 1] - (i - 2) * f[i - 2] - (i - 5) * f[i - 3] + (i - 3) * f[i - 4];
return;
}
void Solve(void)
{
cout << f[n] << edl;
return;
}
int main(void)
{
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
// #ifdef cincoutcmd
// freopen("cin.txt","r",stdin);
// freopen("cout.txt","w",stdout);
// #endif
Init();
while (cin >> n)
Solve();
return 0;
}
AC代码2:
// #define NDEBUG
#include <bits/stdc++.h>
using namespace std;
namespace AIN
{
using db = double;
using ll = long long;
#define edl '\n'
#define str string
#define pll pair<ll, ll>
#define fir first
#define sec second
#define heap priority_queue
#define SPO(n) fixed << setprecision(n)
#define FOR(i, l, r) for (auto i = l; i <= (r); ++i)
#define ROF(i, r, l) for (auto i = r; i >= (l); --i)
#ifdef debugcmd
#define DBG(n) cout << "!!! " << #n << ": " << n << edl
#else
#define DBG(n) ;
#endif
template <typename T>
T KSM(T base, long long exp)
{
// assert(exp >= 0);
T res = 1;
while (exp)
{
if (exp & 1)
res *= base;
base *= base;
exp >>= 1;
}
return res;
}
long long __lcm(long long lhs, long long rhs) { return lhs / __gcd(lhs, rhs) * rhs; }
// constexpr db PI = acos(-1.0);
// constexpr db EPS = 1.0e-9;
constexpr long long LNF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int INF = 0x3f3f3f3f;
// constexpr long long MOD = 998244353;
// constexpr long long MOD = 1e9 + 7;
constexpr long long MOD = 7777777;
constexpr int MXN = 1e3 + 5;
}
using namespace AIN;
template <long long P>
struct ModInt
{
public:
ModInt() : _v(0) {}
template <typename T>
ModInt(T v) { _v = ((long long)v % P + P) % P; }
long long val() const { return _v; }
ModInt &operator++()
{
++_v;
if (_v == P)
_v = 0;
return *this;
}
ModInt &operator--()
{
if (_v == 0)
_v = P;
--_v;
return *this;
}
ModInt operator++(int)
{
ModInt oldVal = *this;
++*this;
return oldVal;
}
ModInt operator--(int)
{
ModInt oldVal = *this;
--*this;
return oldVal;
}
ModInt &operator+=(const ModInt &rhs)
{
_v += rhs._v;
_v %= P;
return *this;
}
ModInt &operator-=(const ModInt &rhs)
{
_v -= rhs._v;
_v = (_v + P) % P;
return *this;
}
ModInt &operator*=(const ModInt &rhs)
{
_v *= rhs._v;
_v %= P;
return *this;
}
ModInt &operator/=(const ModInt &rhs) { return *this = *this * rhs.inv(); }
ModInt operator+() const { return *this; }
ModInt operator-() const { return ModInt() - *this; }
ModInt pow(long long exp) const
{
// assert(exp>=0);
ModInt res = 1;
ModInt base = *this;
while (exp)
{
if (exp & 1)
res *= base;
base *= base;
exp >>= 1;
}
return res;
}
ModInt inv() const
{
// assert(_v);
return pow(P - 2);
}
friend ModInt operator+(const ModInt &lhs, const ModInt &rhs)
{
ModInt res = lhs;
res += rhs;
return res;
}
friend ModInt operator-(const ModInt &lhs, const ModInt &rhs)
{
ModInt res = lhs;
res -= rhs;
return res;
}
friend ModInt operator*(const ModInt &lhs, const ModInt &rhs)
{
ModInt res = lhs;
res *= rhs;
return res;
}
friend ModInt operator/(const ModInt &lhs, const ModInt &rhs)
{
ModInt res = lhs;
res /= rhs;
return res;
}
friend bool operator==(const ModInt &lhs, const ModInt &rhs) { return lhs._v == rhs._v; }
friend bool operator!=(const ModInt &lhs, const ModInt &rhs) { return lhs._v != rhs._v; }
friend std::istream &operator>>(std::istream &is, ModInt &aim)
{
long long tmp;
is >> tmp;
aim = ModInt(tmp);
return is;
}
friend std::ostream &operator<<(std::ostream &os, const ModInt &aim) { return os << aim.val(); }
private:
long long _v;
};
using mint = ModInt<MOD>;
const ll LIM = 1e3 + 3;
ll n;
mint f[2][MXN][MXN];
bool vis[MXN];
ll v[MXN];
ll p[MXN];
void Init(ll n)
{
FOR(i, 1, n)
vis[i] = false;
v[0] = -1;
p[0] = -1;
return;
}
void DFS(ll pos, ll num, ll len)
{
if (pos == len)
{
ll flag = 0;
if (p[len] == p[len - 1] + 1 || p[len] == p[len - 1] - 1)
flag = 1;
ll cnt = 0;
FOR(i, 1, len - 1)
if (v[i] == v[i + 1] + 1 || v[i] == v[i + 1] - 1)
++cnt;
++f[flag][len][cnt];
return;
}
FOR(i, 1, len)
{
if (!vis[i])
{
vis[i] = true;
v[pos + 1] = i;
p[i] = pos + 1;
DFS(pos + 1, i, len);
vis[i] = false;
}
}
return;
}
void Pre(void)
{
FOR(i, 1, 5)
{
Init(i);
DFS(0, -1, i);
}
FOR(i, 6, LIM)
FOR(j, 0, i - 1)
{
f[0][i][j] = f[0][i - 1][j + 1] * (j + 1) + f[1][i - 1][j + 1] * j + f[0][i - 1][j] * (i - j - 2) + f[1][i - 1][j] * (i - j - 1);
f[1][i][j] = f[1][i - 1][j - 1] + f[1][i - 1][j] + f[0][i - 1][j - 1] * 2;
}
return;
}
void Solve(void)
{
cout << f[0][n][0] << edl;
return;
}
int main(void)
{
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
// #ifdef cincoutcmd
// freopen("cin.txt","r",stdin);
// freopen("cout.txt","w",stdout);
// #endif
Pre();
while (cin >> n)
Solve();
return 0;
}