解析
不能在一条思路上死磕!
首先这题真正考的其实就是
p
=
3
p=3
p=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_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=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;
}
/*
*/