1. 程式人生 > >2017湘潭賽 A題 Determinant (高斯消元取模)

2017湘潭賽 A題 Determinant (高斯消元取模)

mina while 代數 tor mod continue 高斯消元 problem 元素

鏈接

http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1260

今年湘潭的A題

題意不難

大意是把n*(n+1)矩陣去掉某一列

求去掉那一列之後的對應的行列式的值 mod 1e9+7

思路1 :

先做一次高斯消元

得到一個階梯矩陣 只有最後兩列沒有被消元

然後每去掉一列 拿出新的矩陣 做一次消元

1 a12 a13 a14

0 1 a23 a24

0 0 1 a34

假設去掉第一列

a12 a13 a14

1 a23 a24

0 1 a34

把第一行添到到最後一行後面

1 a23 a24

0 1 a34

a12 a13 a14

再做一次消元

1 a23 a24

0 1 a34

0 0 s44

然後這一行的ans 就是 s44* 消元的系數

(註意消元時候的除法用逆元 以及去掉最後兩列時直接在最初的消元好的矩陣中求解 不再做新的消元)

代碼 :

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int mod = 1e9+7;
 4 int pow_mod(int
n,int m) 5 { 6 int ret=1; 7 while (m){ 8 if (m&1)ret=1LL*ret*n%mod; 9 n=1LL*n*n%mod; 10 m>>=1; 11 } 12 return ret; 13 } 14 vector<int> a[500]; 15 vector<int> st[500]; 16 int ans1[500]; 17 int ans2[500]; 18 inline int up_mod(long long x) 19 {
20 return ((x%mod)+mod)%mod; 21 } 22 int main() 23 { 24 int n; 25 int i,j,k,l; 26 while (~scanf("%d",&n)){ 27 n--; 28 int v; 29 for (i=1;i<=n;i++){ 30 a[i].clear(); 31 a[i].push_back(0); 32 ans1[i]=ans2[i]=1; 33 for (j=1;j<=n+1;j++){ 34 scanf("%d",&v); 35 a[i].push_back(v); 36 } 37 }ans1[n+1]=ans2[n+1]=1; 38 if (n==1){ 39 printf("%d %d\n",a[1][2],a[1][1]); 40 continue ; 41 } 42 int det=1; 43 for (i=1;i<=n;i++){ 44 for (j=i;j<=n;j++){ 45 if (a[j][i]>0)break; 46 } 47 if (j==n+1)continue; 48 if (j!=i){ 49 swap(a[i],a[j]); 50 det=up_mod(-det); 51 } 52 det=up_mod(1LL*det*a[i][i]); 53 int inv=pow_mod(a[i][i],mod-2); 54 for (j=i;j<=n+1;j++)a[i][j]=up_mod(1LL*inv*a[i][j]); 55 for (j=i+1;j<=n;j++){ 56 int tmp=a[j][i]; 57 for (k=i;k<=n+1;k++){ 58 a[j][k]=up_mod(a[j][k]-1LL*tmp*a[i][k]); 59 } 60 } 61 } 62 /* for (i=1;i<=n;i++,puts(""))for (j=1;j<=n+1;j++)printf("%12d",a[i][j]);*/ 63 for (i=1;i<=n-1;i++){ 64 int pre=1; 65 for (j=1;j<=n;j++){ 66 if (j==i)st[n]=a[i]; 67 else st[pre++]=a[j]; 68 } 69 for (k=i+1;k<=n;k++){ 70 if (!st[n][k])continue; 71 int tmp=st[n][k]; 72 for (j=k;j<=n+1;j++){ 73 st[n][j]=up_mod(st[n][j]-1LL*st[k-1][j]*tmp); 74 } 75 }/*puts(""); 76 for (j=1;j<=n;j++,puts("")){ 77 for (k=1;k<=n+1;k++)printf("%10d",st[j][k]); 78 }*/ 79 int ans=st[n][n+1]; 80 pre=1; 81 int mm=det; 82 if ((n-i)&1)mm=up_mod(-det); 83 printf(i==1?"%d":" %d",up_mod(1LL*mm*ans)); 84 } 85 printf(" %d %d\n",up_mod(1LL*det*a[n][n+1]),det); 86 } 87 return 0; 88 }

ac 運行時間為218ms

第二種思路是在開頭加一行數 然後題目相當於求第一行每個元素對應的代數余子式

等價於求伴隨矩陣

下面的代碼是qls的 借來一用 思路很清晰

利用逆矩陣求伴隨矩陣

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<ctime>
 6 #include<iostream>
 7 #include<algorithm>
 8 using namespace std;
 9 const int MAXN=205;
10 const int Mod=1000000007;
11 int a[MAXN][MAXN],b[MAXN][MAXN];
12 int get_rand(int x)//[0,x)
13 {
14     int t=1;
15     while((1<<t)<x)t++;
16     int res=x;
17     while(res>=x)
18     {
19         res=0;
20         for(int i=0;i<t;i++)
21             res|=(rand()%2)<<i;
22     }
23     return res;
24 }
25 int fp(int a,int k)
26 {
27     int res=1;
28     while(k)
29     {
30         if(k&1)res=1LL*res*a%Mod;
31         a=1LL*a*a%Mod;
32         k>>=1;
33     }
34     return res;
35 }
36 void solve(int n)
37 {
38     for(int i=1;i<=n;i++)
39         for(int j=1;j<=n;j++)
40             b[i][j]=(i==j);
41     int det=1;
42     for(int i=1;i<=n;i++)
43     {
44         int t=i;
45         for(int k=i;k<=n;k++)
46             if(a[k][i])t=k;
47         if(t!=i)det*=-1;
48         for(int j=1;j<=n;j++)
49         {
50             swap(a[i][j],a[t][j]);
51             swap(b[i][j],b[t][j]);
52         }
53         det=1LL*a[i][i]*det%Mod;
54         int inv=fp(a[i][i],Mod-2);
55         for(int j=1;j<=n;j++)
56         {
57             a[i][j]=1LL*inv*a[i][j]%Mod;
58             b[i][j]=1LL*inv*b[i][j]%Mod;
59         }
60         for(int k=1;k<=n;k++)
61         {
62             if(k==i)continue;
63             int tmp=a[k][i];
64             for(int j=1;j<=n;j++)
65             {
66                 a[k][j]=(a[k][j]-1LL*a[i][j]*tmp%Mod+Mod)%Mod;
67                 b[k][j]=(b[k][j]-1LL*b[i][j]*tmp%Mod+Mod)%Mod;
68             }
69         }
70     }
71     det=(det+Mod)%Mod;
72     for(int i=1;i<=n;i++)
73         for(int j=1;j<=n;j++)
74             b[i][j]=1LL*det*b[i][j]%Mod;
75 }
76 int main()
77 {
78     srand(time(NULL));
79     int n;
80     while(scanf("%d",&n)!=EOF)
81     {
82         for(int j=1;j<=n;j++)
83             a[1][j]=2;
84         for(int i=2;i<=n;i++)
85             for(int j=1;j<=n;j++)
86                 scanf("%d",&a[i][j]);
87         solve(n);
88         for(int i=1;i<=n;i++)
89             printf("%d%c",(i&1 ? b[i][1] : (Mod-b[i][1])%Mod)," \n"[i==n]);
90     }
91     return 0;
92 }

2017湘潭賽 A題 Determinant (高斯消元取模)