zoukankan      html  css  js  c++  java
  • 【CF895C】Square Subsets(线性基)

    点此看题面

    • 给定(n)个元素,问有多少非空子集满足乘积为完全平方数。
    • (nle10^5,a_ile70)

    完全平方数与线性基

    一个数是完全平方数,等价于它的每个质因子的次数都是偶数。

    考虑到(a_ile70),质因子个数很少,因此我们可以直接把每个数质因数分解,由于一个数的贡献只需要考虑它的每种质因数次数的奇偶性,所以就可以被表示为一个二进制数。

    这样一来,一个非空子集的乘积为完全平方数,当且仅当其中数对应的二进制数异或和为(0)

    要判断有多少数异或和为(0)就很简单,只要把所有数插入线性基,那么线性基外的每个数都可以表示为线性基中若干数的异或和,进而线性基外的每个非空集合都可以表示为线性基中若干数的异或和。

    所以假设线性基外有(t)个数,则答案就是(2^t-1)

    代码:(O(19n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define X 1000000007
    using namespace std;
    const int Pt=19,P[19]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67};//预先存下所有质数
    struct LB {int v[Pt];I bool A(RI x) {for(RI i=Pt-1;~i;--i) if(x>>i&1) {if(v[i]) x^=v[i];else return v[i]=x;}return 0;}}B;//线性基
    int main()
    {
    	RI n,i,x,v,t=0;scanf("%d",&n);W(n--) {for(scanf("%d",&x),v=i=0;i^Pt;++i) W(!(x%P[i])) x/=P[i],v^=1<<i;!B.A(v)&&++t;}
    	RI p=1;for(i=1;i<=t;++i) p=2LL*p%X;return printf("%d
    ",p-1),0;//2^t-1
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    实验三 进程调度模拟程序
    实验二作业调度模拟程序实验报告
    实验8
    实验七
    实验六
    实验五 数独游戏界面设置
    实验五
    实验四
    实验三
    实验二
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF589C.html
Copyright © 2011-2022 走看看