Zhu and 772002---hdu5833(高斯消元解求异或方程组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5833

题意:给n个数,选择一些数字乘积为平方数的选择方案数。

分析:每一个数字分解质因数。比如4, 6, 10, 15,, 令

表示选择第i个数字,那么,如果p是平方数,那么每个质因数上的指数为偶数,x1系数为2已经是偶数不考虑。可以转换为异或为0判断偶数,即奇数置为1,偶数置为0,然后n个数字m个质因数的增广矩阵消元看有几个自由变量(取0或1无所谓),答案是2^r - 1(全部都不取方案不算)

线性方程组的自由变量个数了(即方程个数 - 增广矩阵的秩)。 

比如:n=2个数  8 =2^3 、 9 = 3^2

有两个素因子2和3,可列出两个方程:

3*X1 + 0*X2 = 0 (mod2)                     等价于 :                        X1 +0*X2 = 0 

0*X1 + 2*X2 = 0 (mod2)                                                            0*X1 + 0*X2 = 0

其中只有1个有效方程,即秩为1。

这代表什么意思呢? X1 = 0 , 表示8一定不能选 , X2不确定,表示9可以选择也可以不选。

因此答案为 2^1 - 1  = 1   (因为不允许一个都不选,所以减一)

网选原题的并不只这一题,没做过的只能默默吃亏了;

相对应的UVA的11542:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2537同时也是大白书上的例题;

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
#define N 2000
#define met(a, b) memset(a, b, sizeof(a))
#define mod 1000000007
typedef long long LL;

int f[N*10], p[N*100], Matrix[N][N];

int Prime()
{
    int cnt = 0;
    for(int i=2; i<N; i++)
    {
        if(!p[i])f[cnt++] = i;
        for(int j=i; j<N; j+=i)
            p[j] = 1;
    }
    return cnt;
}

int gauss(int m, int n)
{
    int i = 0, j = 0;
    while(i<m && j<n)
    {
        int row = i;
        for(int k=i+1; k<m; k++)
        {
            if(Matrix[k][j])
            {
                row = k;
                break;
            }
        }
        if(Matrix[row][j])
        {
            if(row != i)
            {
                for(int k=0; k<=n; k++)
                    swap(Matrix[i][k], Matrix[row][k]);
            }
            for(int p=i+1; p<m; p++)
            {
                if(Matrix[p][j])
                {
                    for(int q=i; q<=n; q++)
                        Matrix[p][q] ^= Matrix[i][q];
                }
            }
            i++;
        }
        j++;
    }
    return i;
}

int main()
{
    int PrimeNum = Prime();

    int n, T, t = 1;

    scanf("%d", &T);
    while(T--)
    {
        met(Matrix, 0);
        scanf("%d", &n);
        int m = 0;
        for(int i=0; i<n; i++)
        {
            LL num;
            scanf("%I64d", &num);
            for(int j=0; j<PrimeNum; j++)
            {
                if(num%f[j] == 0)
                {
                    m = max(m, j);
                    while(num%f[j] == 0)
                    {
                        num/=f[j];
                        Matrix[j][i] ^= 1;
                    }
                }
            }
        }
        int ret = gauss(m+1, n);

        LL ans = 1;
        for(int i=1; i<=n-ret; i++)
        {
            ans = ans*2%mod;
        }
        ans = (ans+mod-1) % mod;
        printf("Case #%d:
%I64d
", t++, ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5773396.html