首页 > 代码库 > 2017湘潭赛 A题 Determinant (高斯消元取模)
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 (高斯消元取模)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。