2572. 无平方子集计数(状态压缩dp)

简介: 2572. 无平方子集计数(状态压缩dp)

题目

思路

  • 类似01背包优化的状态压缩dp(误)
  • 首先按照数字分出是否有平方子集,然后再计数cnt[x]
  • 枚举合法的数字(2 ~ 30),为什么不算1?因为所有的1都有两种状态,选或者不选(或者说他不算是质数),直接在最后的结果上2cnt[1]2^{cnt[1]}2cnt[1]即可
  • 枚举所有状态(0 ~ 1 << 10, 倒着来是类似01背包的优化),如果和当前状态mask互不相交,递推至mask|j
  • 最后无平方子集的数量就是(∑0210f)∗2cnt[1]−1(\sum_0^{2^{10}}f) * 2^{cnt[1]} - 1(0210f)2cnt[1]1

代码

ini

复制代码

const int mod = 1e9 + 7;
int sum[31];
int p[30] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
typedef long long LL;
LL f[(1 << 11) + 10];
class Solution {
public:
    int squareFreeSubsets(vector<int> &nums)
    {
        for (int i = 2; i <= 30; i++) 
        {
            for (int j = 0; j < 10; j++)
            {
                if (i % p[j] == 0)
                {
                    if (i % (p[j] * p[j]) == 0)
                    {
                        sum[i] = -1;
                        break;
                    }
                    sum[i] = sum[i] | (1 << j);
                }
            }
        }
        map<int,int>cnt;
        for(int i = 0;i < nums.size();i++)
            cnt[nums[i]]++;
        int v = 1 << 10;
        memset(f,0,sizeof f);
        f[0] = 1;
        for(auto it : cnt)
        {
            int a = it.first;
            int b = it.second;
            int mask = sum[a];
            if(mask > 0)
            {
                for(int i = v;i >= 0;i--)
                {
                    if((i & mask) == 0)
                    {
                        f[i | mask] = (f[i] * b + f[i | mask]) % mod;
                    }
                }
            }
        }
        LL ans = 0;
        int x = cnt[1];
        int y = 1;
        while(x)
        {
            y = y * 2 % mod;
            x--;
        }
        for(int i = 0;i < 1 << 10;i++)
        {
            ans = (f[i] + ans) % mod;
        }
        ans = (ans * y) % mod;
        return (ans+ mod - 1) % mod;
    }
};


相关文章
|
2天前
|
算法 测试技术 C++
【差分数组】【图论】【分类讨论】【整除以2】3017按距离统计房屋对数目
【差分数组】【图论】【分类讨论】【整除以2】3017按距离统计房屋对数目
|
2天前
|
算法 测试技术 C#
【数位dp】【数论】【动态规划】2999. 统计强大整数的数目
【数位dp】【数论】【动态规划】2999. 统计强大整数的数目
|
2天前
|
算法 测试技术 C#
【差分数组】【图论】【分类讨论】【整除以2】100213按距离统计房屋对数目
【差分数组】【图论】【分类讨论】【整除以2】100213按距离统计房屋对数目
【差分数组】【图论】【分类讨论】【整除以2】100213按距离统计房屋对数目
|
9月前
|
算法
算法篇之二分查找(第74题探索二维矩阵、第287题寻找重复数)
算法篇之二分查找(第74题探索二维矩阵、第287题寻找重复数)
82 0
|
10月前
|
算法 内存技术
求组合数三种算法
求组合数三种算法
50 0
|
11月前
|
算法
规律数求和
规律数求和
70 0
给你一组数,求出其中两两最大公约数中最大的值
给你一组数,求出其中两两最大公约数中最大的值
46 0
|
存储 算法
算法 |【实验5.3】:一元三次方程的根-连续区间的二分搜索求近似解
算法 |【实验5.3】:一元三次方程的根-连续区间的二分搜索求近似解
126 0
算法 |【实验5.3】:一元三次方程的根-连续区间的二分搜索求近似解
|
算法 测试技术
力扣每日一题:477.汉明距离总和 字符串矩阵与列表计数器 双解分析!
力扣每日一题:477.汉明距离总和 字符串矩阵与列表计数器 双解分析!
89 0
|
机器学习/深度学习 索引
798. 得分最高的最小轮调 : 上下界分析 + 差分应用
798. 得分最高的最小轮调 : 上下界分析 + 差分应用