zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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)," 
    "[i==n]);
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    算法竞赛入门经典第一章习题解答
    程序实现求int类型和double类型的最大最小值范围
    程序实现求int类型和double类型的最大最小值范围
    程序实现求int类型和double类型的最大最小值范围
    程序实现求int类型和double类型的最大最小值范围
    机器狗组装费用 南邮NOJ 1076 优先权队列
    【HDOJ】2604 Queuing
    【HDOJ】1208 Pascal's Travels
    【HDOJ】4857 逃生
    【HDOJ】2510 符号三角形
  • 原文地址:https://www.cnblogs.com/orz010orz/p/6891578.html
Copyright © 2011-2022 走看看