2017湘潭赛 A题 Determinant (高斯消元取模)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017湘潭赛 A题 Determinant (高斯消元取模)相关的知识,希望对你有一定的参考价值。

链接

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 (高斯消元取模)的主要内容,如果未能解决你的问题,请参考以下文章

XTU 1261 - Roads - [最小割][2017年湘潭邀请赛(江苏省赛)B题]

XTU 1260 - Determinant

2017-5-14 湘潭市赛 Strange Optimization

2017CCPC中南地区赛 H题(最长路)

2017年中国大学生程序设计竞赛-中南地区赛暨第八届湘潭市大学生计算机程序设计大赛游记心得

2019年湘潭大学程序设计竞赛(重现赛)