zoukankan      html  css  js  c++  java
  • Codeforces 895C

    895C - Square Subsets

    思路:状压dp。

    每个数最大到70,1到70有19个质数,给这19个质数标号,与状态中的每一位对应。

    状压:一个数含有这个质因子奇数个,那么他状态的这一位是1,一个数含有这个这个质因子偶数个,那么状态的这一位是0。

    那么如果一个数是平方数,那么这个数的状态每一位都是0,即状态为0。

    状态转移见代码。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e5+5;
    const int MOD=1e9+7;
    int a[N];
    int cnt[75];
    int dp[75][(1<<19)+5];
    int s[75];
    int prime[19]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67};
    int _2p[N];
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        for(int i=1;i<=70;i++)
        {
            int t=i;
            for(int j=0;j<19;j++)
            {
                while(t%prime[j]==0)t/=prime[j],s[i]^=(1<<j);
            }
        }
        _2p[0]=1;
        for(int i=1;i<N;i++)_2p[i]=(_2p[i-1]*2)%MOD;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i],cnt[a[i]]++;
        dp[0][0]=1;
        for(int i=1;i<=70;i++)
        {
            if(!cnt[i])
            {
                for(int j=0;j<(1<<19);j++)
                dp[i][j]=dp[i-1][j];
            }
            else
            {
                for(int j=0;j<(1<<19);j++)
                {
                    dp[i][j^s[i]]=((ll)dp[i][j^s[i]]+(ll)_2p[cnt[i]-1]*dp[i-1][j])%MOD;//从cnt[i]个数个选奇数个,C(n,1)+C(n,3)+...=2^(n-1)
                    dp[i][j]=((ll)dp[i][j]+(ll)_2p[cnt[i]-1]*dp[i-1][j])%MOD;//从cnt[i]个数个选偶数个,C(n,0)+C(n,2)*C(n,4)+...=2^(n-1)
                }
            }
        }
        cout<<(dp[70][0]-1)%MOD<<endl;//减去0的情况
    return 0; }
  • 相关阅读:
    你读了该博客中哪些超链接?有何感想
    最理想的师生关系是健身教练和学员的关系,在这种师生关系中你期望获得来自老师的哪些帮助?
    1500802028 王莉娟
    解码方法
    N皇后问题
    两个链表的交叉
    全排列
    交叉字符串
    翻转链表
    爬楼梯
  • 原文地址:https://www.cnblogs.com/widsom/p/7910385.html
Copyright © 2011-2022 走看看