zoukankan      html  css  js  c++  java
  • Subsets Forming Perfect Squares

     题意:

    给出n个数字,选出若干个数字,使得这些数字的乘积是一个完全平方数,问有多少种选法。

    解法:

    考虑异或方程组,$x_i$表示第i个数字是否选,

    注意到只要保证结果中各个质因数都出现偶数次就可保证结果是一个完全平方数。

    相当于每个因数出现的次数$mod  2 = 0$。

    这样对于每一个质因子,我们可以得到一个有n个变量的异或方程。

    求矩阵中自由元的个数$cnt$,答案就是$2^{cnt}-1$

    注意本题中变量数可能远大于方程数,我们不能普通地Jordan。

    只要消成阶梯矩阵,并求出矩阵的秩即可。

    用$bitmask$压位,可以做到$O(frac{n^3}{64})$

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <bitset>
     5 
     6 #define N 2010
     7 #define LL long long
     8 #define P 1000000007LL
     9 
    10 using namespace std;
    11 
    12 bitset<N> g[N];
    13 bool v[N];
    14 int tot,prime[N];
    15 LL a[N];
    16 
    17 LL solve(int n,int m)
    18 {
    19     LL ans=1LL;
    20     int k=1; 
    21     for(int i=1;i<=m;i++)
    22     {
    23         int t=0;
    24         for(int j=k;j<=n;j++)
    25             if(g[j][i])
    26             {
    27                 t=j;
    28                 break;
    29             }
    30         if(!t)
    31         {
    32             ans=ans*2LL%P;
    33             continue;
    34         }
    35         swap(g[t],g[k]);
    36         for(int j=k+1;j<=n;j++)
    37             if(j!=k && g[j][i])
    38                 g[j]^=g[k];
    39         k++;
    40     }
    41     return (ans-1LL+P)%P;
    42 }
    43 
    44 int main()
    45 {
    46     for(int i=2;i<=2000;i++)
    47     {
    48         if(v[i]) continue;
    49         prime[++tot]=i;
    50         for(int j=i+i;j<=2000;j+=i)
    51             v[j]=1;
    52     }
    53     int T,n,Te=0;
    54     cin>>T;
    55     while(T--)
    56     {
    57         cin>>n;
    58         for(int i=1;i<=tot;i++) g[i].reset();
    59         for(int i=1;i<=n;i++)
    60         {
    61             cin>>a[i];
    62             for(int j=1;j<=tot;j++)
    63             {
    64                 LL tmp=a[i];
    65                 while(tmp%prime[j]==0)
    66                 {
    67                     g[j][i]=g[j][i]^1;
    68                     tmp/=prime[j];
    69                 }
    70             }
    71         }
    72         printf("Case #%d:
    ",++Te);
    73         cout << solve(tot,n) << endl;
    74     }
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    IOS 获取时间的问题
    JQ 点赞
    截取字符串第一个空格前的字符
    JQ 的一些方法
    匿名函数var a =function(){}和function a(){}的区别
    完美支持中文编程的 Emacs 配置文件 .emacs
    linux find 命令忽略某个或多个子目录的方法
    Linux下如何用date设置时间
    nagios的监控代码!
    shell脚本监控apache进程数和oracle连接数
  • 原文地址:https://www.cnblogs.com/lawyer/p/6558863.html
Copyright © 2011-2022 走看看