1. 程式人生 > >HDU - 5755:Gambler Bo (開關問題,%3意義下的高斯消元)

HDU - 5755:Gambler Bo (開關問題,%3意義下的高斯消元)

關於 tin () 不用 sin main std swa --

pro:給定N*M的矩陣,每次操作一個位置,它會增加2,周圍4個位置會增加1。給定初始狀態,求一種方案,使得最後的數都為0;(%3意義下。

sol:(N*M)^3的復雜度的居然過了。 好像標程是M^3的,因為第一排確定了,後面的都確定了。所以我們只要設關於第一排的方程,那麽跑下來,第N+1排的都為0,則合法。

(此題由於3的特殊性,x關於3的逆元=x;所以不用求逆元

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int
maxn=1010; int a[maxn][maxn],ans[maxn]; int x[4]={0,0,1,-1}; int y[4]={1,-1,0,0}; void Guass(int N) { rep(i,0,N-1){ int t=i; rep(j,i+1,N-1) if(a[j][i]>a[t][i]) t=j; if(i!=t) rep(j,i,N) swap(a[i][j],a[t][j]); if(!a[i][i]) continue; rep(j,i+1,N-1){
if(!a[j][i]) continue; int t1=a[i][i],t2=a[j][i];//保留,不用直接帶進去 rep(k,i,N) a[j][k]=((a[j][k]*t1-a[i][k]*t2)%3+3)%3; } } for(int i=N-1;i>=0;i--){ a[i][N]=a[i][N]*a[i][i]%3; rep(j,0,i-1) a[j][N]=((a[j][N]-a[i][N]*a[j][i])%3
+3)%3; } } int main() { int T,N,M,S,t,p; scanf("%d",&T); while(T--){ scanf("%d%d",&N,&M); S=N*M; rep(i,0,S) rep(j,0,S) a[i][j]=0; rep(i,0,N-1) rep(j,0,M-1){ t=i*M+j; scanf("%d",&a[t][S]); a[t][S]=3-a[t][S]; } rep(i,0,S-1) a[i][i]=2; rep(i,0,N-1) rep(j,0,M-1){ t=i*M+j; rep(k,0,3) { if(i+x[k]>=0&&i+x[k]<N&&j+y[k]>=0&&j+y[k]<M){ a[(i+x[k])*M+j+y[k]][t]=1; } } } Guass(S); int res=0; rep(i,0,S-1) res+=a[i][S]; printf("%d\n",res); rep(i,0,S-1){ p=i/M+1; t=i%M+1; if(a[i][S]) printf("%d %d\n",p,t); if(a[i][S]==2) printf("%d %d\n",p,t); } } return 0; }

HDU - 5755:Gambler Bo (開關問題,%3意義下的高斯消元)