zoukankan      html  css  js  c++  java
  • HDU 5833 (2016大学生网络预选赛) Zhu and 772002(高斯消元求齐次方程的秩)

      网络预选赛的题目……比赛的时候没有做上,确实是没啥思路,只知道肯定是整数分解,然后乘起来素数的幂肯定是偶数,然后就不知道该怎么办了…

      最后题目要求输出方案数,首先根据题目应该能写出如下齐次方程(从别人那里盗的……):

      a11*x1  ^  a12*x2  ^  ...  ^  a1n*xn=0

      a21*x1  ^  a22*x2  ^  ...  ^  a2n*xn=0

      ...

      an1*x1  ^  an2*x2  ^  ...  ^  ann*xn=0,Aij表示选的第j个数的第i个质数(可能有些人跟我有一样的疑问,为什么不是第i个数的第j个质数呢,这是为了方便消元计算),xi为1或者0,代表数选和不选。

      所以这个问题就化成了该方程有几个解的问题,该方程的特征矩阵有303行,n列,因为1-2000之间一共有303个素数,实际可以省略用不到的那些。

      然后,学过线性代数的童鞋都知道,当它的特征矩阵的秩是n的时候,该方程有唯一解,就是0解,所以当时我们求出秩来以后,如果秩是r且r < n,也就意味着有n-r个0行,同时意味着,它与其它行线性相关,也就是这一行不影响答案,有选和不选两种情况,一共就有2的(n-r)次方 种情况,求秩的方法用高斯消元的模板,类比成异或就可以了,当时我还自己写了一个消元的函数,发现不对……还是贴的人家的模板。

      代码及注释如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define LL long long
    #define N 305
    #define mod 1000000007
    LL a[N];
    int prime[N],tot,n,m;
    int fenjie[N][N],zhuan[N][N];
    bool yes(int x)
    {
        for(int i = 2; i*i <= x; i++)
        {
            if(x%i == 0) return false;
        }
        return true;
    }
    void Make_P()///暴力版素数表,实在懒得改……
    {
        tot = 0;
        for(int i = 2; i <= 2000; i++)
        {
            if(yes(i)) prime[tot++] = i;
        }
    }
    void FenJie()///质因数分解
    {
        memset(fenjie,0,sizeof(fenjie));
        m = -99;
        for(int i = 0; i < n; i++)
        {
            LL tmp = a[i];
            for(int j = 0; j < tot; j++)
            {
                while(tmp % prime[j]==0)
                {
                    fenjie[j][i]++;
                    tmp /= prime[j];
                    m = max(m,j);///取一个最大的j值即可
                }
                fenjie[j][i] %= 2;
                if(tmp == 1) break;
            }
        }
        m++;
    }
    int Rank()///高斯消元求秩[j][i]的形式派上了用场
    {
        int i=0,j=0,k,r,u;
        while(i < m && j < n)
        {
            r = i;
            for(k=i; k<m; k++)
            {
                if(fenjie[k][j])
                {
                    r=k;
                    break;
                }
            }
            if(fenjie[r][j])
            {
                if(r != i)
                    for(k=0; k <= n; k++)swap(fenjie[r][k],fenjie[i][k]);
                for(u=i+1; u<m; u++)
                    if(fenjie[u][j])
                        for(k=i; k<=n; k++)
                            fenjie[u][k]^=fenjie[i][k];
                i++;
            }
            j++;
        }
        return i;
    }
    
    int mypow(int x,int y)
    {
        int res = 1;
        for(int i = 1; i <= y; i++)
        {
            res = ((x%mod)*(res%mod)) % mod;
        }
        return res;
    }
    int Slove()
    {
        int mi = n-Rank();
        return (mypow(2,mi) - 1) % mod;
    }
    int main()
    {
    //    freopen("in1.cpp","r",stdin);
        int t,ca=0;
        Make_P();
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i = 0; i < n; i++)
            {
                cin>>a[i];
            }
            FenJie();
            printf("Case #%d:
    ",++ca);
            cout<<Slove()<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Haskell Interactive Development in Emacs
    Access Java API in Groovy Script
    手工设置Eclipse文本编辑器的配色
    Color Theme of Emacs
    Gnucash的投资记录
    Special Forms and Syntax Sugars in Clojure
    Use w3m as Web Browser
    SSE指令集加速之 I420转BGR24
    【图像处理】 增加程序速度的方法
    TBB 入门笔记
  • 原文地址:https://www.cnblogs.com/jifahu/p/5773381.html
Copyright © 2011-2022 走看看