最近是真的什么题都做不出来啊
感觉正解藏的稍微深一点就看不出来了
考虑按
1
∼
n
1\sim n
1 ∼ n 的顺序插入序列。将答案除以
n
n
n 即可。
那么我们唯一要干的事情就是把哪些位置是 固定的 给找出来。
首先,如果一个数小于等于
i
−
4
i-4
i − 4 ,那么它的旁边都不能插数,可以看作是固定的。并且对于小于等于
i
−
4
i-4
i − 4 的数,因为在后续填数的过程中不会影响其左右两边的数,因此在当前状态下一定是合法的。换言之,当填入
i
i
i 过后,我们只需要检验
i
−
3
i-3
i − 3 是否合法即可。故而,我们只需要关注
i
−
3
,
i
−
2
,
i
−
1
i-3,i-2,i-1
i − 3 , i − 2 , i − 1 的相对位置关系,以及是否相邻。这显然可以用最暴力的状压解决,然后就做完了。这玩意用顺逆时针来记录会更简单一些,剩下的全部是手动分讨。
我承认,这个做法非常垃圾。这也导致了代码非常难打。
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
const int N=1e6 +5 ;
const int mod=1e9 +7 ;
int n,K,D,p[3 ],ban[N][10 ],now[2 ][8 ],nxt[2 ][8 ],res,state[N];
vector<int >vec;
void add (int &x,int y) {x=(x+y)%mod;}
int check () {
vec.clear ();
for (int i=1 ;i<=n;i++){
if (!state[i]){
vec.pb (i);
}
}
for (int i=n;i>=1 ;i--){
if (state[i]){
vec.pb (i);
}
}
for (int i=0 ;i+1 <vec.size ();i++){
if (ban[vec[i]][vec[i+1 ]-vec[i]+3 ])return 0 ;
}
if (ban[vec.back ()][vec[0 ]-vec.back ()+3 ])return 0 ;
return 1 ;
}
int check (int x,int y) {
return ban[x][y-x+3 ];
}
void solve1 (int x,int s) {
int sig=s>>1 &1 ;
if ((s&1 )&&(!(s&4 )||!check (x-1 ,x-3 ))&&!check (x-3 ,x)){
add (nxt[0 ][4 |sig],now[0 ][s]);
}
if ((s&2 )&&(!(s&1 )||!check (x-3 ,x-2 ))&&(!(s&4 )||!check (x-1 ,x-3 ))){
add (nxt[1 ][3 ],now[0 ][s]);
}
if ((s&4 )&&(!(s&1 )||!check (x-3 ,x-2 ))&&!check (x,x-3 )){
add (nxt[0 ][2 |sig],now[0 ][s]);
}
}
void solve2 (int x,int s) {
int sig=s>>1 &1 ;
if ((s&1 )&&(!(s&4 )||!check (x-2 ,x-3 ))&&!check (x-3 ,x)){
add (nxt[1 ][2 |(sig<<2 )],now[1 ][s]);
}
if ((s&2 )&&(!(s&1 )||!check (x-3 ,x-1 ))&&(!(s&4 )||!check (x-2 ,x-3 ))){
add (nxt[0 ][6 ],now[1 ][s]);
}
if ((s&4 )&&(!(s&1 )||!check (x-3 ,x-1 ))&&!check (x,x-3 )){
add (nxt[1 ][1 |(sig<<2 )],now[1 ][s]);
}
}
int solve () {
if (D==0 ){
if (n==1 )return 1 ;
return 0 ;
}
if (D==1 ){
if (n==1 )return 1 ;
else if (n==2 ){
if (ban[1 ][2 -1 +3 ]||ban[2 ][1 -2 +3 ])return 0 ;
return 1 ;
}
else {
return 0 ;
}
}
if (D==2 ){
if (n==1 )return 1 ;
else if (n==2 ){
if (ban[2 -1 +3 ]||ban[1 -2 +3 ])return 0 ;
return 1 ;
}
for (int i=1 ;i<=n;i+=2 )state[i]=0 ;
for (int i=2 ;i<=n;i+=2 )state[i]=1 ;
res+=check ();
state[1 ]=0 ;
for (int i=2 ;i<=n;i+=2 )state[i]=0 ;
for (int i=3 ;i<=n;i+=2 )state[i]=1 ;
res+=check ();
return res;
}
if (n==1 ){
return 1 ;
}
if (n==2 ){
if (ban[2 -1 +3 ]||ban[1 -2 +3 ])return 0 ;
return 1 ;
}
now[0 ][7 ]=now[1 ][7 ]=1 ;
for (int i=4 ;i<=n;i++){
memset (nxt,0 ,sizeof nxt);
for (int j=0 ;j<2 ;j++){
for (int k=0 ;k<8 ;k++){
if (now[j][k]){
if (j==0 ){
solve1 (i,k);
}
else {
solve2 (i,k);
}
}
}
}
memcpy (now,nxt,sizeof nxt);
}
for (int i=0 ;i<2 ;i++){
for (int j=0 ;j<8 ;j++){
if (now[i][j]){
if (i==0 ){
if ((!(j&1 )||!check (n-2 ,n-1 ))&&(!(j&2 )||!check (n-1 ,n))&&(!(j&4 )||!check (n,n-2 ))){
add (res,now[i][j]);
}
}
else {
if ((!(j&1 )||!check (n-2 ,n))&&(!(j&2 )||!check (n,n-1 ))&&(!(j&4 )||!check (n-1 ,n-2 ))){
add (res,now[i][j]);
}
}
}
}
}
return res;
}
int main () {
ios::sync_with_stdio (false );
cin.tie (0 ),cout.tie (0 );
cin>>n>>K>>D;
for (int i=1 ;i<=K;i++){
int a,b;cin>>a>>b;
if (abs (a-b)<=3 ){
ban[a][b-a+3 ]=1 ;
}
}
cout<<solve ();
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」