CF736D Permutations

Link
我们可以把它转化成二分图匹配。
矩阵\(\mathbf A\)满足\(a_{i,j}=[\exists e(i,j)]\),那么总的方案就是\(\sum\limits_{p}\prod\limits_{i=1}^na_{i,p_i}\)
显然\(1\equiv-1\pmod2\),因此总的方案就是\(\det(\mathbf A)\)
考虑容斥,对于不选\((i,j)\)的方案,我们可以用总方案减去强制选的方案。
题目告诉我们\(\det(\mathbf A)\equiv1\pmod2\),那么我们只需要计算强制选的方案的奇偶性然后取个反就好了。
强制选\((i,j)\)的方案其实就是\(M_{i,j}\)也就是\(C_{i,j}\)
我们知道\(\mathbf A^{-1}=\frac{\mathbf A^*}{\det(\mathbf A)}\),因为\(\det(\mathbf A)\equiv1\pmod2\),所以\(\mathbf A^{-1}\)存在并且\(\mathbf A^*=\mathbf A^{-1}\)
那么我们Gauss消元求出\(\mathbf A^{-1}\)就能求出\(\mathbf A^*\)了,而根据定义我们知道\(C_{i,j}=\mathbf A^*_{j,i}\)
注意到这是一个\(01\)矩阵,因此我们可以用bitset优化。

#include<cstdio>
#include<bitset>
#include<utility>
#define pi pair<int,int>
#define fi first
#define se second
using std::pair;
using std::bitset;
using std::swap;
int read(){int x;scanf("%d",&x);return x;}
bitset<4007>a[2007];pi e[500007];
int main()
{
    int n=read(),m=read();
    for(int i=1,u,v;i<=m;++i) e[i]={u=read(),v=read()},a[u][v]=1;
    for(int i=1;i<=n;++i) a[i][i+n]=1;
    for(int i=1;i<=n;++i)
    {
	if(!a[i][i]) for(int j=i+1;j<=n;++j) if(a[j][i]) {swap(a[j],a[i]);break;}
	for(int j=1;j<=n;++j) if(j^i&&a[j][i]) a[j]^=a[i];
    }
    for(int i=1;i<=m;++i) puts(a[e[i].se][e[i].fi+n]? "NO":"YES");
}
posted @ 2020-01-14 17:14  Shiina_Mashiro  阅读(172)  评论(0编辑  收藏  举报