2016CCPC网选 1002:Zhu and 772002(求解矩阵秩)

    xiaoxiao2025-11-10  7

    http://acm.hdu.edu.cn/showproblem.php?pid=5833

    问题概述:输入n个数,可以从当中选出一些数,使得这些数乘积为一个完全平方数,求出总共有多少种不同选法

    (不能不选)(http://acm.hdu.edu.cn/showproblem.php?pid=5833)

    输入样例:                                     对应输出:

    2                                                     Case #1:

    3                                                     3

    3 3 4                                               Case #2:

    3                                                     3

    2 2 2

    高斯消元:

    ①对于n行m列增广矩阵,初始化p==q==1

    ②遍历第p行第q列及下面的所有元素,找到一个非0元,如果找到执行步骤③,没有找到q++,继续执行步骤②,直

    到q超过m,执行步骤④

    ③将这一行和第p行交换,交换后再遍历p行q列下面的每一个元素,如果当前元值不为0,则通过行变换将这行所有

    元素减去p行元素的一定比例,使得当前元为0,遍历完毕,p++,q++,继续执行步骤②

    ④矩阵已经化为阶梯形矩阵,矩阵的秩就是p-1, 方程组不同解的个数就是2^(n-p+1)

    此题题解:

    定理:每个平方数的质因子都有偶数个,而若干个数相乘就是将它们的质因数加在一起

    设一个矩阵,矩阵中的元素a[i][j]==0表示第i个元素可以分解出偶数个第j个质因数,a[i][j]==1表示第i个元素可以分解

    出奇数个第j个质因数,而这题可以将这个矩阵看做成一个方程组的系数矩阵,且这个方程组每一个方程都等于0,

    又因为这道题不允许一个数不选,所以矩阵的全0解非法!最后的答案便是方程组解的个数-1

    附录:线性方程组解的判断:

    设矩阵A为系数矩阵,列向量b为方程对应的值,矩阵B=(A,b)(增广矩阵),n为未知数的个数(列数)

    则有:①R(A)<R(B)      ------      无解

    ②R(A)==R(B)==n      ------      有一个解

    ③R(A)==R(B)<n      ------      有多个解

    PS:当b为0向量时,方程组为线性齐次方程组,不可能无解(像这道题就是个01线性齐次方程组)

    #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define mod 1000000007 int pri[2100], a[2100] = {1,1}; int solve(int A[][305], int n, int m); int main(void) { int T, i, j, k, n, mxj, cas, ans, ret, A[305][305]; long long x; k = 0; for(i=2;i<=2000;i++) { if(a[i]==1) continue; pri[++k] = i; for(j=i*i;j<=2000;j+=i) a[j] = 1; } scanf("%d", &T); cas = 1; while(T--) { mxj = 0; scanf("%d", &n); memset(A, 0, sizeof(A)); for(i=1;i<=n;i++) { scanf("%lld", &x); for(j=1;j<=k;j++) { while(x%pri[j]==0) { mxj = max(mxj, j); x /= pri[j]; A[j][i] ^= 1; } } } ret = solve(A, mxj, n); ans = 1; for(i=1;i<=n-ret;i++) ans = (ans*2)%mod; printf("Case #%d:\n%d\n", cas++, ans-1); } return 0; } int solve(int A[][305], int n, int m) { int i, j, p, r, q; p = q = 1; while(p<=n && q<=m) { r = -1; for(i=p;i<=n;i++) { if(A[i][q]) r = i; } if(r==-1) { q++; continue; } for(i=1;i<=m;i++) swap(A[r][i], A[p][i]); for(i=p+1;i<=n;i++) { if(A[i][q]) { for(j=q;j<=m;j++) A[i][j] ^= A[p][j]; } } p++, q++; } return p-1; }

    转载请注明原文地址: https://ju.6miu.com/read-1304054.html
    最新回复(0)