• HDU 5833 Zhu and 772002(高斯消元)


    题意:给n个数,从n个数中抽取x(x>=1)个数,这x个数相乘为完全平方数,求一共有多少种取法,结果模1000000007。

    思路:每个数可以拆成素数相乘的形式,例如:

     x1   2=2^1 * 3^0 * 5^0;

     x2   3=2^0 * 3^1 * 5^0;

     x3   4=2^2 * 3^0 * 5^0;

     x4   5=2^0 * 3^0 * 5^1;

     x5   6=2^1 * 3^1 * 5^0;

     x6   15=2^0 * 3^1 * 5^1;

    用xi表示第i个数选或不选,xi的取值为0或1;因为相乘结果为完全平方数,所以最后的完全平方数表示成素数相乘的形式后,每个素数的幂一定是偶数,即模2等于0:

     2   (x1+2*x3+x5)%2=0

     3   (x2+x5+x6)%2=0

     5   (x4+x6)%2=0

    将上面的式子转化为异或方程组,求解有m个自由变量,每个自由变量都可以取0或1,最终答案为2^m-1(去掉全0的情况);

    #include <bits/stdc++.h>
    using namespace std;
    #define MAXN 2000
    int prime[MAXN+5];
    int a[MAXN+5][305];
    int free_num;
    int free_x[MAXN];
    int x[310];
    int equ,var;
    const int mod=1000000007;
    void getprime()
    {
        int i,j;
        memset(prime,1,sizeof(prime));
        prime[0]=prime[1]=0;
        for(i=2;i<=MAXN;i++)
        {
            if(prime[i])
                prime[++prime[0]]=i;
            for(j=1;j<=prime[0]&&i*prime[j]<=MAXN;j++)
            {
                prime[i*prime[j]]=0;
                if(i%prime[j]==0)
                    break;
            }
        }
    }
    void geta(int id,long long num)
    {
        int i;
        i=1;
        while(num!=1)
        {
            while(num%prime[i]==0)
            {
                num/=prime[i];
                a[i-1][id]^=1;
            }
            i++;
        }
    }
    //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数
    int Gauss()
    {
        int max_r, col, k;
        free_num = 0;
        for(k = 0, col = 0; k < equ && col < var; k++, col++)
        {
            max_r = k;
            for(int i = k ; i < equ; i++)
                if(abs(a[i][col]==1)
                {
                    max_r = i;
                    break;
                }
            if(a[max_r][col] == 0)
            {
                k--;
                free_x[free_num++] = col; //自由变元
                continue;
            }
            if(max_r != k)
            {
                for(int j = col; j < var+1; j++)
                    swap(a[k][j],a[max_r][j]);
            }
            for(int i = k+1; i < equ;i++)
                if(a[i][col] != 0)
                    for(int j = col; j < var+1;j++)
                        a[i][j] ^= a[k][j];
        }
        for(int i = k;i < equ;i++)
            if(a[i][col] != 0)
                return -1;
        if(k < var)return var-k;
        return 0;
    }
    int main()
    {
        int ans;
        int t;
        int n;
        int i;
        int cas;
        int freex;
        long long num;
        scanf("%d",&t);
        getprime();
        //printf("%d
    ",prime[0]);
        for(cas=1;cas<=t;cas++)
        {
            memset(a,0,sizeof(a));
            scanf("%d",&n);
            for(i=0;i<n;i++)
            {
                scanf("%I64d",&num);
                geta(i,num);
            }
            equ=prime[0];
            var=n;
            freex=Gauss();
            //printf("::%d
    ",freex);
            if(freex==-1)
                ans=0;
            else if(freex==0)
                ans=0;
            else
            {
                ans=1;
                for(i=0;i<freex;i++)
                {
                    ans=(2*ans)%mod;
                }
                ans--;
            }
            printf("Case #%d:
    %d
    ",cas,ans);
        }
        return 0;
    }
    View Code

     

  • 相关阅读:
    动态规划 ------最短路径问题
    回溯算法 ------回溯算法的设计思想和适用条件
    回溯算法 ------ 回溯算法的设计思想及适用条件
    回溯算法 ------回溯算法的几个例子
    纯css实现翻书效果
    从vue源码看props
    js循环中使用async/await踩过的坑
    js实现word转换为html
    从vue源码看Vue.set()和this.$set()
    微信、qq二次分享
  • 原文地址:https://www.cnblogs.com/vwqv/p/5774034.html
Copyright © 2020-2023  润新知