bzoj 4031 [HEOI2015]小Z的房间

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4031

见TJ:https://blog.csdn.net/fromatp/article/details/53966305

因为模数不是质数,所以高斯消元里的那个除法不能用。所以辗转相除。

辗转相除的那个除法可以用。因为本质是在模意义下相减。那个除法不能用是因为乘上那个浮点数不一定能消成真的0。

其实不用把Matrix都弄出来。定义一个数组,直接在上面操作,邻接矩阵+1的时候直接减在那个矩阵上就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int N=85;const ll mod=1e9;
int n,m,tot,dy[15][15];
ll ans=1;
char ch[2][15];
bool fx;
struct Matrix{
    ll a[N][N];
    Matrix(){memset(a,0,sizeof a);}
    Matrix operator - (const Matrix &b)const
    {
        Matrix c;
        for(int i=1;i<=tot;i++)
            for(int j=1;j<=tot;j++)
                c.a[i][j]=(a[i][j]-b.a[i][j]+mod)%mod;
        return c;
    }
}d,l,r;
void add(int x,int y)
{
    d.a[x][x]++;d.a[y][y]++;
    l.a[x][y]=l.a[y][x]=1;
}
void gauss()
{
    for(int i=1;i<=tot;i++)
    {
        int k=i;
        for(int j=i+1;j<=tot;j++)if(r.a[j][i]>r.a[k][i])k=j;
        if(k!=i)
        {
            fx=!fx;for(int l=i;l<=tot;l++)swap(r.a[i][l],r.a[k][l]);
        }
        for(int j=i+1;j<=tot;j++)
            while(r.a[j][i])
            {
                ll tmp=r.a[i][i]/r.a[j][i];
                for(int l=i;l<=tot;l++)
                {
                    ll tp=r.a[i][l];r.a[i][l]=r.a[j][l];        // i=j
                    r.a[j][l]=(tp-r.a[j][l]*tmp%mod+mod)%mod;    // j=i%j
                }
                fx=!fx;
            }
        (ans*=r.a[i][i])%=mod;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int u=(i&1),v=!u;
        scanf("%s",ch[u]+1);
        for(int j=1;j<=m;j++)
            if(ch[u][j]=='.')
            {
                tot++;dy[u][j]=tot;
                if(ch[v][j]=='.')add(dy[v][j],tot);
                if(ch[u][j-1]=='.')add(dy[u][j-1],tot);
            }
    }
    r=d-l;
    tot--;gauss();
    printf("%lld",fx?(-ans+mod)%mod:ans);//(-ans+mod)%mod
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Narh/p/9251093.html
今日推荐