湘潭CCPC A題

Determinant

題意是給有一個n-1行n列的矩陣
讓我們求去掉任意一列,得到的行列式的值(模1e9+7),也就是n個答案
最壞的做法枚舉每一列然後消元,複雜度O(n³*n),顯然不太可行
可以這麼做,先做一次高斯消元得到一個階梯矩陣,然後枚舉每一列,枚舉到第i列,把i+1到n-1列 往上移動一格,即(做一次消元)
x x x x x x x
0 x x x x x x
0 0 x x x x x
0 0 0 x x x x
0 0 0 0 x x x
0 0 0 0 0 x x
如這樣,我們當前枚舉到第3列時,
x x x x x x x
0 x x x x x x
0 0 x x x x x
0 0 0 x x x x
0 0 0 0 x x x
0 0 0 0 0 x x
把第4到6列向上做一次消元,然後乘一下,
第一次寫矩陣變換,有些地方忘了取模結果爆了long long

  #include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<iostream>
#include<stdlib.h>
using namespace std;
#define  LONG long long
const int   INF=0x3f3f3f3f;
const LONG  MOD=1e9+ 7;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
#define lson  l , mid , rt<< 1
#define rson  mid + 1 ,r , (rt<<1)+1
#define root 1, m , 1
LONG matr[220][229] ;
LONG  ans[220 ] ;
LONG tmp_matr[220][210] ;
LONG Q_pow(LONG a , LONG b)
{
    LONG c =  1;
    while(b)
    {
        if(b&1)
         c = (c * a) % MOD ;
        a = (a * a) % MOD ;
        b /= 2;
    }
    return c ;
}
LONG  Gauss (int n )
{
    LONG sign = 1 ;
    for(int t = 1 ; t <= n ; ++ t)
    {
        if(matr[t][t] == 0 )
        {
            for(int i = t + 1; i <= n ; ++ i)
                if(matr[i][t] != 0 )
                {
                    for(int j = 1 ; j <= n + 1 ; ++j)
                        swap(matr[t][j] , matr[i][j]) ;

                    sign = -sign ;
                    break ;
                }
        }
        for(int i = t +1; i <= n ; ++ i)
        {
            LONG x = matr[i][t] ;
            LONG y = matr[t][t] ;
            if( y == 0) break ;
            if( x == 0) continue ;
            LONG tmp = x * Q_pow(y , MOD - 2 ) % MOD  ;  //這裏記得取模 否則下面會爆long long
            for( int j = 1 ; j <= n + 1; ++ j )
                matr[i][j] = ( matr[i][j] - ( matr[t][j] * tmp % MOD ) +MOD )% MOD;
        }
    }
    LONG res = sign ;
    for(int i = 1; i<= n ;++i)
        res = (res * matr[i][i] )% MOD ;
    return (res + MOD )% MOD ;
}
int main()
{
//freopen("/home/weyoung/桌面/in","r",stdin);
//freopen("/home/weyoung/桌面/out2","w",stdout);
    int n ;
    while(cin >> n)
    {
        for(int i = 1 ; i <= n - 1  ; ++i)
            for(int j =1 ; j <= n ;++j)
            cin >> matr[i][j], matr[i][j] = (matr[i][j] + MOD ) % MOD ;
        ans[n] = Gauss(n-1 ) ;
        for(int t = n-1; t >= 1 ; -- t )
        {
            LONG res = 1;
            LONG sign = 1 ;
            for(int i = 1 ;i < n ; ++ i)
                for(int j =1; j<= n ; ++j)
                tmp_matr[i][j] = matr[i][j] ;
                //
            for(int j =1; j <= t-1 ; ++ j )
            res = (res * tmp_matr[j][j]) % MOD ;
            for(int i = t + 1; i < n ; ++ i)
            {
                if(tmp_matr[i-1][i] == 0)
                {
                    sign = - sign ;
                    for(int j = t + 1 ; j<= n ;++j)
                    swap(tmp_matr[i][j] , tmp_matr[i-1][j] ) ;
                }
                else if(tmp_matr[i][i] == 0) continue ;
                else
                {
                    LONG x = tmp_matr[i][i] ;
                    LONG y = tmp_matr[i-1][i] ;
                    LONG temp = x * Q_pow( y , MOD - 2) % MOD ; //這裏取模 否則同樣會爆long long
                    for(int j = t+ 1 ;j <= n ;++j)
                    tmp_matr[i][j] = ( tmp_matr[i][j] - (tmp_matr[i-1][j] * temp % MOD ) + MOD  ) % MOD ;

                }
                res = (res * tmp_matr[i-1][i]) % MOD ;
            }
            res = ( (res * sign  + MOD ) * tmp_matr[n-1][n] ) % MOD ;;
            ans[t] = (res + MOD) % MOD ;
        }
        for(int i =1; i<= n -1; ++ i)
            cout<<ans[i]<<" " ;
            cout<<ans[n]<<endl;
    }
    return 0 ;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章