解析
不能在一条思路上死磕!
首先这题真正考的其实就是 p=3p=3p=3。
乍一看题意:给出一张特殊图,求哈密顿回路方案数。
然后发现这个图性质不咋地。
然后就不会了。
…
正解根本和哈密顿回路毛关系也没有!
考虑从1-n依次插入。
注意到,插入i的时候,我们其实只关注i-3,i-2,i-1(不妨称其为“关键元素”)互相之间是否相邻。
实现上,由于有环,所以可能还要记录最左和最右的关键元素是否靠边。
把这个状态状压下来,直接转移即可。
口胡一时爽,实现火葬场。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
using namespace std;const int N=1e6+100;
const int inf=1e9;
const int mod=1e9+7;
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}inline ll ksm(ll x,ll k){ll res=1;while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res;
}#define add(x,y) (x+=y,x>=mod?x-=mod:0)int n,m,P;
bool ban[N][10];
int o=5;
struct bruteforce{int ans,a[5];int vis[5];void dfs(int k){if(k>n){bool flag=1;for(int i=1;i<=n;i++){if(abs(a[i]-a[i%n+1])>P||ban[a[i]][a[i]-a[i%n+1]+o]) flag=0;}ans+=flag;return;}for(int i=2;i<=n;i++){if(vis[i]) continue;a[k]=i;vis[i]=1;dfs(k+1);vis[i]=0;}return;}void work(){ans=0;a[1]=1;dfs(2);printf("%d\n",ans);return;}
}bf;
int aa[N];
inline bool check(){for(int i=1;i<=n;i++){if(abs(aa[i+1]-aa[i])>P) return false;if(ban[aa[i]][aa[i]-aa[i+1]+o]) return false;}return true;
}
void work2(){ aa[1]=aa[n+1]=1;int p,num=1;for(p=2;;p+=2){aa[++num]=p;if(p==n){p--;break;}else if(p==n-1){p++;break;}}while(p>1){aa[++num]=p;p-=2;}int res=0;res+=check();reverse(aa+2,aa+1+n);res+=check();printf("%d\n",res);
}
const int bas=4;
inline int Hash(int *x){int res=0;for(int i=1;i<=3;i++) res=res*bas+x[i];return res;
}
int a[5],tmp[10];
int tot,p[N][4],op1[N][3],op2[N][3],tr[N][5],vis[5];
//op1: xiang lin
//op2: kao bian
int id[1050][4][4];
void get(int x,int y){++tot;for(int i=1;i<=3;i++) p[tot][i]=a[i];op1[tot][0]=(x>>1)&1;op1[tot][1]=x&1;op2[tot][0]=(y>>1)&1;op2[tot][1]=y&1;id[Hash(a)][x][y]=tot;//print(tot);
}
void dfs(int k,int x,int y){if(k>3){get(x,y);return;}for(int i=1;i<=3;i++){if(vis[i]) continue;vis[i]=1;a[k]=i;dfs(k+1,x,y);vis[i]=0;}return;
}
inline int ins(int x,int pos){ int num=0;int cur[4],cnt=0;for(int i=0;i<=3;i++){ if(i){tmp[++num]=a[i]-1;}if(i==pos){tmp[++num]=3;} if(i==0&&!op2[x][0]) tmp[++num]=0;if(i==1&&!op1[x][0]) tmp[++num]=0;if(i==2&&!op1[x][1]) tmp[++num]=0;if(i==3&&!op2[x][1]) tmp[++num]=0; }for(int i=1;i<=num;i++){if(tmp[i]) cur[++cnt]=i;}int f1(0),f2(0);if(cur[1]+1==cur[2]) f1|=2;if(cur[2]+1==cur[3]) f1|=1;if(cur[1]==1) f2|=2;if(cur[3]==num) f2|=1;num=0;for(int i=0;i<=3;i++){if(i){if(a[i]>1)tmp[++num]=a[i]-1;}if(i==pos){tmp[++num]=3;}}return id[Hash(tmp)][f1][f2];
}
void solve(int x){memcpy(a,p[x],sizeof(p[x]));if(op2[x][0]&&op2[x][1]){tr[x][0]=ins(x,0);tr[x][3]=ins(x,3);}if(op1[x][0]) tr[x][1]=ins(x,1); if(op1[x][1]) tr[x][2]=ins(x,2);
}
int f[2][150],now,pre;
void init(int k){if(k>3){f[now][id[Hash(a)][3][3]]=1;return;}for(int i=1;i<=3;i++){if(vis[i]) continue;vis[i]=1;a[k]=i;init(k+1);vis[i]=0;}return;
}
inline bool prelink(int x,int pl){if(pl==1) return op2[x][0]&&op2[x][1];else return op1[x][pl-2];
}
inline bool suflink(int x,int pl){if(pl==3) return op2[x][0]&&op2[x][1];else return op1[x][pl-1];
}
void work3(){for(int i=0;i<=3;i++){for(int j=0;j<=3;j++){dfs(1,i,j);}}//debug("tot=%d\n",tot);for(int i=1;i<=tot;i++) solve(i);now=1;pre=0;init(1);for(int i=4;i<=n;i++){swap(now,pre);memset(f[now],0,sizeof(f[now]));for(int j=1;j<=tot;j++){if(!f[pre][j]) continue;a[1]=p[j][1];a[2]=p[j][2];a[3]=p[j][3];int pl=a[1]==1?1:(a[2]==1?2:3);for(int k=0;k<=3;k++){if(!tr[j][k]) continue;int frt= k==pl-1?4:a[(pl+1)%3+1],suf=k==pl?4:a[pl%3+1];if(k==0&&pl==3) suf=4;if(k==3&&pl==1) frt=4; if(prelink(j,pl)&&ban[i-3+frt-1][frt-1+o]) continue;if(suflink(j,pl)&&ban[i-3][1-suf+o]) continue;add(f[now][tr[j][k]],f[pre][j]);}}}ll ans=0;for(int i=1;i<=tot;i++){ bool flag=1;memcpy(a,p[i],sizeof(p[i]));for(int j=1;j<=3&&flag;j++){int pre=(j+1)%3+1,suf=j%3+1;if(prelink(i,j)&&ban[n-3+a[pre]][a[pre]-a[j]+o]){flag=0;}else if(suflink(i,j)&&ban[n-3+a[j]][a[j]-a[suf]+o]){flag=0;}}if(flag) add(ans,f[now][i]);}ans=ans*ksm(n,mod-2)%mod;printf("%lld\n",ans);return;
}
signed main(){
#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifn=read();m=read();P=read();for(int i=1;i<=m;i++){int x=read(),y=read();if(abs(x-y)<=P) ban[x][x-y+o]=1;}if(n<=3){bf.work();return 0;}if(P<=1){printf("0");return 0;}else if(P==2){work2();return 0;}else work3();return 0;
}
/*
*/