Codeforces Gym 101174 I The White Rabbit Pocket Watch 模线性方程组
Posted polya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Gym 101174 I The White Rabbit Pocket Watch 模线性方程组相关的知识,希望对你有一定的参考价值。
#include<stdio.h> #include <math.h> #include <algorithm> #include <math.h> #include <string.h> using namespace std; const int mod=13; int a[510][200*100+10]; int x[510],id[201][201]; inline int gcd(int a,int b) { while(b!=0) { int t=b; b=a%b; a=t; } return a; } inline int lcm(int a,int b) { return a/gcd(a,b)*b; } #define LL long long LL inv(LL a,LL m) { if(a==1)return 1; return inv(m%a,m)*(m-m/a)%m; } inline int meow(int x) { return (x%mod+mod)%mod; } int gauss(int equ,int var) { int max_r,col,k; for(k=0,col=0;k<equ&&col<var;k++,col++) { max_r=k; for(int i=k+1;i<equ;i++) //找到第col列最大系数行 max_row if(abs(a[i][col])>abs(a[max_r][col])) max_r=i; if(a[max_r][col]==0) //如果该列系数为0 则枚举的当前行数不变 { k--;continue; } if(max_r!=k) //如果最大系数行不是当前行 则交换这两行 for(int j=col;j<=var;j++) swap(a[k][j],a[max_r][j]); for(int i=k+1;i<equ;i++) //对于k行以下的行 { if(a[i][col]!=0) { int LCM=lcm(abs(a[i][col]),abs(a[k][col])); int ta=LCM/abs(a[i][col]); int tb=LCM/abs(a[k][col]); if(a[i][col]*a[k][col]<0)tb=-tb; for(int j=col;j<=var;j++) a[i][j]=meow(a[i][j]*ta-a[k][j]*tb); //用最小公倍数消去当前列的系数 } } } // for(int i=0;i<equ;i++) // for(int j=0;j<=col;j++) // printf("%2d%c",a[i][j],j==col?‘ ‘:‘ ‘); for(int i=k;i<equ;i++) //有全零项和不为0 if(a[i][col]!=0)return -1; if(k<var) return var-k; for(int i=var-1;i>=0;i--) { int tmp=a[i][var]; for(int j=i+1;j<var;j++) { if(a[i][j]!=0) { tmp=meow(tmp-a[i][j]*x[j]); } } x[i]=(tmp*inv(a[i][i],mod))%mod; } // for(int i=0;i<col;i++) // printf("%2d ",x[i]);printf(" "); return 0; } int cnt=0; inline int getid(int x,int y) { if(x>y)swap(x,y); if(id[x][y]!=-1) return id[x][y]; return id[x][y]=cnt++; } int tot[510]; int f[201][201]; int main() { // freopen("in.txt","r",stdin); int n,st,ed,m; scanf("%d%d%d%d",&n,&st,&ed,&m); memset(id,0xff,sizeof id); for(int i=0;i<m;i++) { int k; scanf("%d%d",tot+i,&k); int x,y=0; for(int j=0;j<k;j++) { x=y; scanf("%d",&y); if(j) { int idx=getid(x,y); // if(x==y) while(1); a[i][idx]++; if(a[i][idx]>=mod)a[i][idx]-=mod; } } } for(int i=0;i<m;i++) { a[i][cnt]=tot[i]; } // for(int i=0;i<m;i++) // for(int j=0;j<=cnt;j++) // printf("%d%c",a[i][j],j==cnt?‘ ‘:‘ ‘); int res=gauss(m,cnt); // printf("%d ",res); if(res==-1)while(1); else if(res!=0) f[300][300]=1; // printf("res:%d ",res); // for(int i=0;i<cnt;i++) // printf("%d ",x[i]);printf("%d "); memset(f,0x3f,sizeof f); for(int i=1;i<=n;i++) f[i][i]=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(id[i][j]==-1)continue; // printf("from %d to %d %d ",xx,y,x[id[i]]); f[i][j]=f[j][i]=x[id[i][j]]; } // for(int i=1;i<=n;i++,puts("")) // for(int j=1;j<=n;j++) // printf("%d ",f[i][j]); for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { f[i][j]=min(f[i][j],f[i][k]+f[k][j]); } printf("%d ",f[st][ed]); return 0; }
以上是关于Codeforces Gym 101174 I The White Rabbit Pocket Watch 模线性方程组的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Gym 101174 J Risky Lottery 计算方法 逼近求值 dfs
Codeforces Gym 101174 B Within Arm's Reach 极角排序