矩阵与线性方程组专题

  • 矩阵与线性方程组专题
    • UVA 10870 Recurrences
    • UVA 1386LA 3704 Cellular Automaton
    • UVA 10828 Back to Kernighan-Ritchie
    • UVA 11542 Square
    • UVA 10655 Contemplation Algebra
    • UVA 11149 Power of Matrix
    • UVA 10808 Rational Resistors
    • UVA 1332 Kids Problem

矩阵与线性方程组专题

UVA 10870 Recurrences

题意:第n个Fib数
递推

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) 
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (10)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n) cout<<a[i]<<' '; cout<<endl; 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 

const int MAXN =(20) ;
int n,m,d;
ll a[MAXN];

struct M  
{  
    int n,m;  
    ll a[MAXN][MAXN];  
    M(int _n=0){n=m=_n;MEM(a);} 
    M(int _n,int _m){n=_n,m=_m;MEM(a);}
    void mem (int _n=0){n=m=_n;MEM(a);}
    void mem (int _n,int _m){n=_n,m=_m;MEM(a);}

    friend M operator*(M a,M b)  
    {  
        M c(a.n,b.m);  
        For(k,a.m)
            For(i,a.n)  
                For(j,b.m)  
                    c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%(::m);  
        return c;     
    }  
    void make_I(int _n)  
    {  
        n=m=_n; MEM(a)
        For(i,n) a[i][i]=1;  
    }  
}A;
M pow2(M a,ll b)  
{  
    M c;c.make_I(a.n);    
    static bool a2[1000000];    
    int n=0;while (b) a2[++n]=b&1,b>>=1;    
    For(i,n)    
    {    
        if (a2[i]) c=c*a;    
        a=a*a;    
    }    
    return c;    
}
int f[MAXN];
int main()
{
// freopen("uva10870.in","r",stdin);
// freopen(".out","w",stdout);

    while(cin>>d>>n>>m) {
        if (!d && !n && !m) return 0;

        For(i,d) scanf("%lld",&a[i]);
        For(i,d) scanf("%lld",&f[i]),f[i]%=m;
        if (n<=d) {
            cout<<f[n]<<endl;
            continue;
        }
        A.mem(d);
        For(i,d) For(j,d) {
            if (i<d) A.a[i][j] = (i == j-1 ); else A.a[i][j]=a[d-j+1];
        }
        A=pow2(A,n-d);

        ll ans=0;
        For(j,d) ans = (ans + A.a[d][j] * f[j] %m ) % m;
        cout<<ans<<endl;
    } 


    return 0;
}

UVA 1386/LA 3704 Cellular Automaton

题意:给一个环,上面有n个格子,每次操作把格子的值变为与它距离不超过d的格子在操作之前的值的和%m,求k次操作后的值
1n500,1k107,1106m,0dn/2

列成矩阵,发现要求循环矩阵的k次方
(循环矩阵就是从第二行开始每一行为上一行循环右移一列的结果。)
结论:两个循环矩阵的乘积还是循环矩阵。
循环矩阵只需要保存一行,因此矩阵乘法的复杂度只有 O(n2)

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) 
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl; 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (500 + 10)
int n,m,d,k;
struct M  
{  
    int n,m;  
    ll a[2][MAXN];  
    M(int _n=0){n=m=_n;MEM(a);} 
    M(int _n,int _m){n=_n,m=_m;MEM(a);}
    void mem (int _n=0){n=m=_n;MEM(a);}
    void mem (int _n,int _m){n=_n,m=_m;MEM(a);}

    int get(int i,int j) {
        int t=(j-i+1+n) % n;
        return (t == 0) ? a[1][n] : a[1][t];
    } 

    friend M operator*(M a,M b)  
    {  
        M c(a.n);  
        For(k,a.n)
            For(j,b.m)  
               c.a[1][j]=(c.a[1][j]+a.a[1][k]*b.get(k,j) )%(::m);

        return c;     
    }  
    void make_I(int _n)  
    {  
        n=m=_n; MEM(a)
        a[1][1] = 1; 
    }  
}A,c;
void pow2(ll b)  
{  
    c.make_I(A.n);    
    static bool a2[1000000];    
    int n=0;while (b) a2[++n]=b&1,b>>=1;    
    For(i,n)    
    {    
        if (a2[i]) c=c*A;    
        A=A*A;
    }    
}
ll a[MAXN],ans[MAXN];
int main()
{
// freopen("la3704.in","r",stdin);
// freopen(".out","w",stdout);

    while (cin>>n>>m>>d>>k){
        For(i,n) a[i] = read();

        A.mem(n);
        For(j,n)
            if (min(abs(1-j),n-abs(1-j))<=d) {
                A.a[1][j]=1%m;
            }
        pow2(k);
        A=c;
        For(i,n) {
            ans[i]=0;
            For(j,n) ans[i]=(ans[i] + a[j]*A.get(i,j)%m ) %m;
        }
        PRi(ans,n)
    }
    return 0;
}

UVA 10828 Back to Kernighan-Ritchie

题意:给一个马尔可夫过程,求每个点期望执行次数。
列方程,可能出现矛盾方程,多余方程
不难发现,矛盾方程的情况说明解为无穷大,自由变量的情况说明不在同一连通块。

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) 
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n) cout<<a[i]<<' '; cout<<endl; 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define eps (1e-8)
#define MAXN (100+10)

typedef double Matrix[MAXN][MAXN];

void gauss_jordan(Matrix A, int n) { //矛盾方程和多余方程都可以 A[0..n-1,0..n]
//运行结束后A[i][i]极为第i个变量的值 
    Rep(i,n) {
        int r=i;
        Fork(j,i+1,n-1) {
            if (fabs(A[j][i])>fabs(A[r][i])) r=j;
        }
        if (fabs(A[r][i]) < eps ) continue; 
        if (r>i) {
            Rep(j,n+1) swap(A[r][j],A[i][j]);
        } 

        Rep(k,n) if (k^i) {
            double f = A[k][i] / A[i][i];
            ForkD(j,i,n) A[k][j] -= f * A[i][j];
        }
    }
}
int n,d[MAXN]; 
vector<int> Prev[MAXN];
bool flag[MAXN];
int main()
{
// freopen("uva10828.in","r",stdin);
// freopen(".out","w",stdout);

    int kcase=0;
    while(cin>>n && n ) {
        printf("Case #%d:\n",++kcase);
        For(i,n) Prev[i].clear(),d[i]=0;
        int a,b;
        while(scanf("%d%d",&a,&b)==2 &&a ) {
            Prev[b].pb(a);
            d[a]++;
        }   


        Matrix A;
        Rep(i,n) Rep(j,n+1) A[i][j]=0;
        A[0][n]=1;
        For(i,n){
            A[i-1][i-1]=1;
            int m=SI(Prev[i]);
            Rep(k,m) {
                int j = Prev[i][k];
                A[i-1][j-1] = -1./(double)d[j];
            }
        }
        gauss_jordan(A,n);
        MEM(flag)
        RepD(i,n-1) {
            if (fabs(A[i][i])<eps && fabs(A[i][n]) >eps) flag[i]=1; 
            RepD(j,i-1) if (fabs(A[j][i])>eps && flag[i] ) flag[j]=1; 
        }
        int q=read();
        while(q--) {
            int i=read();i--;
            if (flag[i]) puts("infinity");
            else printf("%.3lf\n",fabs(A[i][i])<eps ? 0:A[i][n] / A[i][i]);
        }

    }

    return 0;
}

UVA 11542 Square

题意:给一堆数,选出至少一个使乘积为完全平方数,求方案数。

gauss_xor方程组,注意位压

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) 
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (10086)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (100000+10)
int p[MAXN],tot;
bool b[MAXN]={0};
void make_prime(int n)
{
    tot=0;
    Fork(i,2,n)
    {
        if (!b[i]) p[++tot]=i;
        For(j,tot)
        {
            if (i*p[j]>n) break;
            b[i*p[j]]=1;
            if (i%p[j]==0) break;  
        }
    }
}
int n;
ll a[MAXN][2];
int gauss(int n) {
    For(i,n) {
        Fork(j,i+1,n) if (a[j][0]>a[i][0] || a[j][0]==a[i][0] && a[j][1]>a[i][1] ) swap(a[i][0],a[j][0]),swap(a[j][1],a[i][1]);
        if (!a[i][1] && !a[i][0]) return i-1;
        For(k,n) if (i^k) {
            if ((a[k][0]^a[i][0])<a[k][0] || (a[k][0]^a[i][0])==a[k][0] && (a[k][1]^a[i][1])<a[k][1] ) 
            {
                a[k][0]^=a[i][0]; a[k][1]^=a[i][1];
            }
        }           
    }
    return n;               
}
int main()
{
// freopen("uva11542.in","r",stdin);
// freopen(".out","w",stdout);
    make_prime(500);
// cout<<tot<<endl;
    int T=read();
    while(T--) {
        n=read();
        For(i,n)
        {
            ll x;
            cin>>x;
            a[i][0]=a[i][1]=0;
            Rep(j,2) {
                 int t=j*60;
                 for(int k=0;k<60;k++)
                    if( 1<=t+k && t+k<=tot)
                        while (x%p[t+k]==0) {
                            a[i][j] ^= 1LL<<k; 
                            x/=p[t+k];
                        }   
            }           
        }

        int p=gauss(n);
        cout<<-1+(1LL<<(n-p))<<endl;
    } 
    return 0;
}

UVA 10655 Contemplation! Algebra

题意:已知 p,q ( p=a+b,q=ab ),求 an+bn
f(n)=an+bn
(an1+bn1)(a+b)=an+bn+ab(an2+bn2)
f(n1)p=f(n)+qf(n2)
f(n)=pf(n1)qf(n2)

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) 
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n) cout<<a[i]<<' '; cout<<endl; 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (10) 
struct M  
{  
    int n,m;  
    ll a[MAXN][MAXN];  
    M(int _n=0){n=m=_n;MEM(a);} 
    M(int _n,int _m){n=_n,m=_m;MEM(a);}
    void mem (int _n=0){n=m=_n;MEM(a);}
    void mem (int _n,int _m){n=_n,m=_m;MEM(a);}

    friend M operator*(M a,M b)  
    {  
        M c(a.n,b.m);  
        For(k,a.m)
            For(i,a.n)  
                For(j,b.m)  
                    c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]);  
        return c;     
    }  
    void make_I(int _n)  
    {  
        n=m=_n; MEM(a)
        For(i,n) a[i][i]=1;  
    }  
}A;
M pow2(M a,ll b)  
{  
    M c;c.make_I(a.n);    
    static bool a2[1000000];    
    int n=0;while (b) a2[++n]=b&1,b>>=1;    
    For(i,n)    
    {    
        if (a2[i]) c=c*a;    
        a=a*a;    
    }    
    return c;    
}
ll p,q,n;
ll f[3];
int main()
{
// freopen("uva10655.in","r",stdin);
// freopen(".out","w",stdout);
    while(scanf("%lld%lld%lld",&p,&q,&n)==3) {

        f[0]=2;
        f[1]=p; f[2]=p*p-2*q;
        if (n<=2) {
            cout<<f[n]<<endl; continue;
        }
        A.mem(2); 
        A.a[1][1]=p;
        A.a[1][2]=-q;
        A.a[2][1]=1;
        A.a[2][2]=0;
        A=pow2(A,n-2);
        cout<<A.a[1][1]*f[2]+A.a[1][2]*f[1]<<endl;
    } 


    return 0;
}

UVA 11149 Power of Matrix

题意:已知 nn 的矩阵 A ,求 A+A2++Ak

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) 
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (10)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (40+4)
struct M  
{  
    int n,m;  
    ll a[MAXN][MAXN];  
    M(int _n=0){n=m=_n;MEM(a);} 
    M(int _n,int _m){n=_n,m=_m;MEM(a);}
    void mem (int _n=0){n=m=_n;MEM(a);}
    void mem (int _n,int _m){n=_n,m=_m;MEM(a);}

    friend M operator*(M a,M b)  
    {  
        M c(a.n,b.m);  
        For(k,a.m)
            For(i,a.n)  
                For(j,b.m)  
                    c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%F;  
        return c;     
    }  
    friend M operator+(M a,M b)  
    {  
        For(i,a.n)  
            For(j,a.m)  
                a.a[i][j]=(a.a[i][j]+b.a[i][j])%F;  
        return a;
    }  
    void make_I(int _n)  
    {  
        n=m=_n; MEM(a)
        For(i,n) a[i][i]=1;  
    }  
}A;
bool a3[1000000];  
M pow222(M a,ll b)  
{  
    M c;c.make_I(a.n);    
    int n=0;while (b) a3[++n]=b&1,b>>=1;
    c=a; b=1;
    M d=c;
    ForD(i,n-1)    
    {    
        b=b*2+a3[i];
        c=c*d+c;
        d=d*d;
        if (a3[i]) c=c*a+a,d=d*a;
    }    
    return c;    
}
int n,k;
int main()
{
// freopen("uva11149.in","r",stdin);
// freopen(".out","w",stdout);

    while(cin>>n>>k) {
        if (!n) break;
        A.mem(n);
        For(i,n) For(j,n) cin>>A.a[i][j],A.a[i][j]%=F;
        A=pow222(A,k);
        PRi2D(A.a,n,n)
        puts("");
    }

    return 0;
}

UVA 10808 Rational Resistors

题意:给一幅n个节点m条导线的电阻网络,求U,V两点间等效电阻。

列节点电压方程
特殊情况:2点不连通,电阻为正无穷

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) 
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
ll gcd(ll a,ll b){if (!b) return a;return gcd(b,a%b);}
class Frac{
public:
    ll a,b;
    Frac():a(0),b(1){}
    Frac(ll _a,ll _b):a(_a),b(_b){deal();}
    void deal() {
        ll d=gcd(a,b);
        a/=d; b/=d;
        if (b<0) a=-a,b=-b;
    }
    Frac operator+ (const Frac &u) {
        Frac ans;
        ans.a = a*u.b + b*u.a;
        ans.b = b*u.b;
        ans.deal();
        return ans;
    }   
    Frac operator- (const Frac &u) {
        Frac ans;
        ans.a = a*u.b - b*u.a;
        ans.b = b*u.b;
        ans.deal();
        return ans;
    }   
    Frac operator* (const Frac &u) {
        Frac ans;
        ans.a = a*u.a;
        ans.b = b*u.b;
        ans.deal();
        return ans;
    }
    Frac operator/ (const Frac &u) {
        Frac ans;
        ans.a = a*u.b;
        ans.b = b*u.a;
        ans.deal();
        return ans;
    }
    void operator+= (Frac u){ *this = *this + u; }
    void operator-= (Frac u){ *this = *this - u; }
    void operator*= (Frac u){ *this = *this * u; }
    void operator/= (Frac u){ *this = *this / u; }

    bool operator< (Frac u) {return a*u.b < b*u.a; }
    bool operator> (Frac u) {return a*u.b > b*u.a; }
    bool operator== (Frac u) {return a*u.b == b*u.a; }
    bool operator<= (Frac u) {return a*u.b <= b*u.a; }
    bool operator>= (Frac u) {return a*u.b >= b*u.a; }
    bool operator!= (Frac u) {return a*u.b != b*u.a; }
    bool operator!= (ll c) {return *this != Frac(c,1); }

    void operator= (ll c){*this = Frac(c,1);    }
    void print(){printf("%lld/%lld",a,b);   }
};
#define MAXN (30)
Frac G[MAXN][MAXN],A[MAXN][MAXN];
class bingchaji
{
public:
    int father[MAXN],n;
    void mem(int _n)
    {
        n=_n;
        For(i,n) father[i]=i;
    }
    int getfather(int x) 
    {
        if (father[x]==x) return x;

        return father[x]=getfather(father[x]);
    }
    void unite(int x,int y)
    {
        father[x]=getfather(father[x]);
        father[y]=getfather(father[y]);
        father[father[x]]=father[father[y]];
    }
    bool same(int x,int y)
    {
        return getfather(x)==getfather(y);
    }
}S;

int n,m;

void gauss_elimination(int n) { //假设系数矩阵A可逆 A[0..n-1,0..n]
//运行结束后A[i][i]极为第i个变量的值 
    Rep(i,n-1) {
        int r=-1;
        Fork(j,i,n-1) {
            if (A[j][i] != 0 ) r=j;
        }   
        if (r<0) continue;
        if (r>i) {
            Rep(j,n) swap(A[r][j],A[i][j]);
        }
        /* 不精确 Fork(k,i+1,n-1) { double f = A[k][i] / A[i][i]; Fork(j,i,n) A[k][j] -= f * A[i][j]; }*/

        Fork(k,i+1,n-1) {
            ForkD(j,i,n-1) A[k][j] -= A[k][i] / A[i][i] * A[i][j];
        }

    }
    RepD(i,n-2) {
        Fork(j,i+1,n-2) A[i][n-1] -= A[j][n-1] * A[i][j];
        A[i][n-1] /= A[i][i];
    }
}
Frac solve(int u,int v) {
    int tn=0,tu,tv,t[MAXN];
    Rep(i,n) {
        if (i==u) tu=tn;
        if (i==v) tv=tn;
        if (S.same(u+1,i+1)) t[tn++]=i;
    }
    tn++;
    Rep(i,tn) Rep(j,tn) A[i][j]=0;

    Rep(i,tn-1)
        Rep(j,tn-1) {
            if (i==j) continue;
            Frac p = G[t[i]][t[j]];
            A[i][i] += p;
            A[i][j] -= p;
        }
    A[tu][tn-1]=1;
    A[tv][tn-1]=-1;
    A[tn-1][0] = 1;

    gauss_elimination(tn);

    return A[tu][tn-1]-A[tv][tn-1];
}

int main()
{
// freopen("uva10808.in","r",stdin);
// freopen(".out","w",stdout);

    int T=read();
    For(kcase,T) {
        printf("Case #%d:\n",kcase);
        n=read(); m=read();
        S.mem(n);

        Rep(i,n) Rep(j,n) G[i][j]=0;

        For(i,m) {
            int u,v,r;
            u=read(); v=read(); r=read();
            if (u==v) continue;
            S.unite(u+1,v+1);
            G[u][v] += Frac(1,r);
            G[v][u] += Frac(1,r);

        }


        int q=read();
        while(q--) {
            int u=read(),v=read();
            printf("Resistance between %d and %d is ",u,v);
            Frac ans;
            if (!S.same(u+1,v+1)) printf("1/0");
            else {
                ans = solve(u,v);
                ans.print();
            }
            puts("");
        }
        puts(""); 
    }

    return 0;
}

UVA 1332 Kid’s Problem

题意:已知一个k元模线性方程组(模数都为 n10
求这个方程是否有解,若有解则输出最小的合法解的和
n16

考虑模方程组消元,可以用辗转相减法
然后暴力搜索,靠玄学拉。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<functional>
#include<cstdlib> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) 
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (n)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
int k,n;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(int a,int b){return (a-b+abs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (30)
#define eps (1e-8)
typedef double Matrix[MAXN][MAXN];
ll Ans=INF;
int x[MAXN];
Matrix f;
void search(int i,int xsum) {
    if (xsum>=Ans) return;
    if (i==-1) {
        Ans=xsum;
        return;
    }
    else {
        int t = f[i][k];
        Fork(j,i+1,k-1) t=sub(t,mul(f[i][j],x[j]));
        Rep(p,n) {
            x[i]=p;
            if (t==mul(x[i],f[i][i])) search(i-1,xsum+p); 
        } 
    }
}
bool fr[MAXN];
void gauss(Matrix A, int n) { 
    Rep(i,n) {
        int r=i;
        Fork(j,i+1,n-1) {
            if (fabs(A[j][i])>fabs(A[r][i])) r=j;
        }
        if (fabs(A[r][i]) < eps ) continue; 
        if (r>i) {
            Rep(j,n+1) swap(A[r][j],A[i][j]);
        } 
        Fork(k,i+1,n-1) {
            while(A[k][i]) {
                if(A[k][i]>=A[i][i]) {
                    Fork(j,i,n) {
                        A[k][j]=sub(A[k][j],A[i][j]);
                    }
                } else {
                    Fork(j,i,n) {
                        A[i][j]=sub(A[i][j],A[k][j]);
                    }
                } 
            }
        }
    }
    Ans=INF;
    search(n-1,0);
    if (Ans==INF) puts("No solution"); 
    else cout<<Ans<<endl;
}

int ans[MAXN];
int main()
{
//  freopen("uva1332.in","r",stdin);
//  freopen(".out","w",stdout);
    while (cin>>k>>n && n) {
        Rep(i,k) ans[i]=(1-read()+n)%n;
        Rep(i,k) Rep(j,k+1) f[i][j]=0;

        Rep(i,k) {
            int p=read();
            Rep(j,p) {
                int a,b;
                cin>>a>>b;
                f[a-1][i]=b;
            }
            f[i][k]=ans[i];
        }

        gauss(f,k);
    }


    return 0;
}

你可能感兴趣的:(uva)