http://uoj.ac/problem/209
奇奇怪怪的解法
然后想了一会发现不能打暴力后 明智的放弃了......
题解只是说把不同的限制去掉 纠结很长时间... 看代码才懂 这样可以搞50分
然后后面很神的把前缀转成后缀 然后讨论下x==y时 就可以统计答案了 好厉害
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 5005
using namespace std;
const int mod=998244353;
int n, m, all, x[MAXN], y[MAXN], mv, f[MAXN], b[MAXN], c[MAXN][MAXN];
void init()
{
c[0][0]=1;
for(int i=1;i<MAXN;++i)
{
c[i][0]=c[i][i]=1;
for(int j=1;j<i;++j)c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
int C(int n,int m)
{
if(n<m||m<0)return 0;
return c[n][m];
}
int cal()
{
f[0]=1;
if(~b[n]&&b[n]!=all)return 0;
b[n]=all;
for(int i=1, j=0;i<=n;++i)
if(~b[i])
f[i]=1ll*f[j]*C(i-j,b[i]-b[j])%mod, j=i;
return f[n];
}
bool check()
{
for(int i=1;i<=n;++i)b[i]=-1;
for(int i=1;i<=m;++i)
{
if(x[i]>y[i])
{
if(~b[x[i]]&&b[x[i]]!=y[i])return 0;
b[x[i]]=y[i];
}
else
{
if(~b[n-y[i]]&&b[n-y[i]]!=all-x[i])return 0;
b[n-y[i]]=all-x[i];
}
}
return 1;
}
int solve()
{
int ans=0;
if(!mv)
{
if(check())ans+=cal();
return ans;
}
if(check()&&(b[mv]==-1||b[mv]==mv)) b[mv]=mv, ans+=cal();
if(check()&&(b[n-mv]==-1||b[n-mv]==all-mv)) b[n-mv]=all-mv, ans=(ans+cal())%mod;
if(check()&&(b[mv]==-1||b[mv]==mv)&&(b[n-mv]==-1||b[n-mv]==all-mv)) b[mv]=mv, b[n-mv]=all-mv, ans=(ans-cal()+mod)%mod;
return ans;
}
int main()
{
init();int cas, t;
scanf("%d",&cas);
while(cas--)
{
mv=m=all=0, scanf("%d%d",&n,&t);
while(t--)
{
++m;
scanf("%d%d",&x[m],&y[m]), all=max(all,min(x[m],y[m]));
if(x[m]==y[m])mv=max(mv,x[m]), --m;
else if(y[m]==n)swap(x[m],y[m]);
}
int ans=0;
for(;all<=n;++all)ans=(ans+solve())%mod;
cout<<ans<<endl;
}
return 0;
}