题目大意是给定一个 n 个点的无向图(没有重边自环)求长度为 5 且没有重复边的路径数。
#include<bits/stdc++.h>
#define int __int128 // 走投无路之举 (:
#define up(i,l,r) for(register int i=l; i<=r; ++i)
#define dn(i,r,l) for(register int i=r; i>=l; --i)
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
using namespace std;
const int N=605, P=1ll<<31;
inline int read() {
int X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') flag=0; ch=getchar(); }
while(ch>='0'&&ch<='9') { X=(X<<1)+(X<<3)+ch-'0'; ch=getchar(); }
if(flag) return X;
return ~(X-1);
}
void write(int X) {
if(X<0) { X=~(X-1); putchar('-'); }
if(X>9) write(X/10);
putchar(X%10+'0');
}
int n, len, toggle[N], F[N][N], f[N][N][6], in[N];
int seed, threshold, state, Ans;
set<pii> edge;
signed main() {
n=read(), seed=read(), threshold=read(), len=read();
up(i,0,len-1) toggle[i]=read();
up(x,0,n-1) up(y,x+1,n-1) {
state=(state*1103515245%P+12345)%P;
if(state<threshold) edge.insert(mp(x,y));
}
up(i,0,len/2-1) {
int x=toggle[2*i], y=toggle[2*i+1];
if(edge.find(mp(x,y))==edge.end()) edge.insert(mp(x,y));
else edge.erase(mp(x,y));
}
for(pii p:edge) {
int x=p.first, y=p.second;
if(y<x) assert(0);
F[x][y]=F[y][x]=1, ++in[x], ++in[y];
}
up(i,0,n-1) up(j,0,n-1) if(i!=j) f[i][j][1]=F[i][j];
up(o,2,5) up(i,0,n-1) {
int sum=0;
up(j,0,n-1) if(i!=j&&F[i][j]) sum+=f[j][i][o-1];
up(j,0,n-1) if(i!=j&&F[i][j]) f[i][j][o]=sum-f[j][i][o-1];
}
up(i,0,n-1) up(j,0,n-1) if(i!=j&&F[i][j]) Ans+=f[i][j][5]; // 走 5 条边且不会连续走一条边的方案数
up(i,0,n-1) up(j,i+1,n-1) {
int bur=0;
up(k,0,n-1) if(k!=i&&k!=j&&F[i][k]&&F[j][k]) ++bur;
if(bur>1) Ans-=4*bur*(bur-1)/2; // 长度为 4 的环
if(F[i][j]&&bur) {
Ans-=2*bur; // 长度为 3 的环
if(in[i]>1) Ans-=3*bur*(in[i]-2); // 长度为 3 的环再带一条边
if(in[j]>1) Ans-=3*bur*(in[j]-2);
}
}
write(Ans);
return 0;
}