zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    请求转发和请求重定向的区别
    查看电脑连过的WiFi密码
    linux mysql不能远程登录
    map的遍历方法
    ________________springbootのMybatis
    ________________springbootのTest
    ________________springbootの自定义starter
    ________________springbootのAOP
    ________________springbootのjdbc、事物
    ________________初学springboot14
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5773396.html
Copyright © 2011-2022 走看看