题目大意:

给出n和k,求从小于等于n的数中取出不超过k个,其乘积是无平方因子数的方案数。无平方因子数:不能被质数的平方整除。

题目分析:

10(枚举\(n\le8\)),40(简单状压\(n\le16\)),70(高级状压\(n\le30\)),100(正解状压n\le500,k\le500)。

对于前百分之70,由于\(n\le30\),质数只有10个,直接状压水。

正解(状压dp+分组背包):

注意到1~n中每个数含有的大于\(\sqrt{n}\)的质因数最多有1种,而\(\sqrt{n}\)内的质数只有8个,于是可以分别对待:

将1~n的数进行分组,含有大于\(\sqrt{n}\)的数分为一组,不含的单独成组,组内的每个元素用8位二进制表示该数含有的小于等于\(\sqrt{n}\)的质因子。

这样分组是因为小于等于\(\sqrt{n}\)的质数只有8个可以方便的进行状压dp,而含有大于\(\sqrt{n}\)质因子(只有1种)的数无法进行状压(时空不够),于是将其放在一个组内,dp时只取出该组中的一个数(保证大于\(\sqrt{n}\)的质因子不平方),从而降低时空。

code:

#include<bits/stdc++.h>
using namespace std;
const int N = 550, Mod = 1e9+7;
int T, n, k, dp[N][(1<<8)+50], state[N], val[N];
const int prime[10] = {2, 3, 5, 7, 11, 13, 17, 19};
vector<int> vec[N];
int main(){
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &k);
for(register int i = 1; i <= n; i++) vec[i].clear(), state[i] = 0;
for(register int i = 1; i <= n; i++){
val[i] = i;
for(register int j = 0; j < 8; j++){
if(val[i] % prime[j] == 0){
val[i] /= prime[j];
if(val[i] % prime[j] == 0){
state[i] = -1; //能够整除质数平方不合法
}
else state[i] |= (1 << j);
}
}
}
for(register int i = 1; i <= n; i++){
if(state[i] == -1) continue;
if(val[i] == 1){
vec[i].push_back(i); //不包含大于sqrtn的质因数
}
else vec[val[i]].push_back(i); //大于等于sqrtn的质因数只可能有一个
}
for(register int i = 1; i <= n; i++)
for(register int j = 0; j < 256; j++)
dp[i][j] = 0;
dp[0][0] = 1;
for(register int i = 1; i <= n; i++){
int vecSze = vec[i].size();
static int tmp[N];
for(register int j = 0; j < vecSze; j++) tmp[j] = state[vec[i][j]]; //卡常操作
for(register int l = k; l >= 1; l--){ //一组之中只能选择一个状态,l倒序
for(register int j = 0; j < vecSze; j++){
for(register int sta = (255^tmp[j]); ; sta = (255^tmp[j]) & (sta - 1)){ //枚举补集,减少一些赘余的状态
dp[l][sta | tmp[j]] = (dp[l][sta | tmp[j]] + dp[l-1][sta]) % Mod;
if(!sta) break;
}
}
}
}
int ans = 0;
for(register int i = 0; i < 256; i++){
for(register int j = 1; j <= k; j++)
ans = (ans + dp[j][i]) % Mod;
}
printf("%d\n", ans);
}
return 0;
}

NOIP模拟 乘积 - 状压dp + 分组背包的更多相关文章

  1. NOI 2015 寿司晚宴 (状压DP+分组背包)

    题目大意:两个人从2~n中随意取几个数(不取也算作一种方案),被一个人取过的数不能被另一个人再取.两个人合法的取法是,其中一个人取的任何数必须与另一个人取的每一个数都互质,求所有合法的方案数 (数据范 ...

  2. HDU - 6125: Free from square (状压DP+分组背包)

    problem:给定N,K.表示你有数1到N,让你最多选择K个数,问有多少种方案,使得选择的数的乘积无平方因子数.N,K<500: solution:显然可以状压DP做,但是500以内的素数还是 ...

  3. HDU 6125 Free from square (状压DP+分组背包)

    题目大意:让你在1~n中选择不多于k个数(n,k<=500),保证它们的乘积不能被平方数整除.求选择的方案数 因为质数的平方在500以内的只有8个,所以我们考虑状压 先找出在n以内所有平方数小于 ...

  4. 树形DP和状压DP和背包DP

    树形DP和状压DP和背包DP 树形\(DP\)和状压\(DP\)虽然在\(NOIp\)中考的不多,但是仍然是一个比较常用的算法,因此学好这两个\(DP\)也是很重要的.而背包\(DP\)虽然以前考的次 ...

  5. HDU 2923 Relocation(状压dp+01背包)

    题目代号:HDU2923 题目链接:http://poj.org/problem?id=2923 Relocation Time Limit: 1000MS Memory Limit: 65536K ...

  6. [CSP-S模拟测试]:点亮(状压DP+树上背包DP)

    题目传送门(内部题121) 输入格式 第一行,一个正整数$n$. 第二行,$n-1$个正整数$p_2,p_3,...,p_n$.保证$p_u$是在$1$到$u-1$中等概率随机选取的. 接下来$n$行 ...

  7. hdu 6125 状压dp+分组

    一道玄学题... 其实一开始想的是对的,优化一下就好了 首先我们会发现,乘积不能被完全平方数整除等价于所有因子的每个质因子个数和都至多为1 可是500以内的质数很多,全找出来会爆炸的 可我们会发现,如 ...

  8. poj 2923 状压dp+01背包

    好牛b的思路 题意:一系列物品,用二辆车运送,求运送完所需的最小次数,两辆车必须一起走 解法为状态压缩DP+背包,本题的解题思路是先枚举选择若干个时的状态,总状态量为1<<n,判断这些状态 ...

  9. BZOJ 4145: [AMPPZ2014]The Prices( 状压dp + 01背包 )

    我自己只能想出O( n*3^m )的做法....肯定会T O( nm*2^m )做法: dp( x, s ) 表示考虑了前 x 个商店, 已买的东西的集合为s. 考虑转移 : 先假设我们到第x个商店去 ...

随机推荐

  1. Android 通过SOCKET下载文件的方法

    本文实例讲述了Android通过SOCKET下载文件的方法.分享给大家供大家参考,具体如下: 服务端代码 import java.io.BufferedInputStream; import java ...

  2. 【Codeforces Round #447 (Div. 2) C】Marco and GCD Sequence

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 把gcd(a[1..n])放在输入的n个数之间. [代码] /* 1.Shoud it use long long ? 2.Have ...

  3. 注意knn与kmeans的区别

    开始的时候,我居然弄混了. knn是分类方法,是通过新加入的节点最接近的N个节点的属性,来判定新的节点. kmeans是聚类方法,是先选择k个点作为k个簇的中点,然后分簇之后重新划定中心点,然后再分簇 ...

  4. UML学习总结(1)——UML学习入门

    随着亲手接触的项目越来越多,项目的复杂度越来越大,项目的理解程度也变的很难,尤其是在接收一个别人已经做好的项目时,你迫切先想到的就是"有没有文档啊",当然是各种文档,概要设计文档, ...

  5. CSS3实现的立体button

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. [Nuxt] Update Vuex State with Mutations and MapMutations in Vue.js

    You commit changes to state in Vuex using defined mutations. You can easily access these state mutat ...

  7. css3-12 transform:scale(1.2,1.2)实现移入元素变大特效

    css3-12 transform:scale(1.2,1.2)实现移入元素变大特效 一.总结 一句话总结:transform:scale(1.2,1.2)鼠标移入的时候变大一点点,超出边框的部分隐藏 ...

  8. 基于深度学习的人脸识别系统系列(Caffe+OpenCV+Dlib)——【四】使用CUBLAS加速计算人脸向量的余弦距离

    前言 基于深度学习的人脸识别系统,一共用到了5个开源库:OpenCV(计算机视觉库).Caffe(深度学习库).Dlib(机器学习库).libfacedetection(人脸检测库).cudnn(gp ...

  9. ZOJ 1108 FatMouse's Speed (HDU 1160) DP

    传送门: ZOJ:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=108 HDU :http://acm.hdu.edu.cn/s ...

  10. [Angular2 Form] patchValue, setValue and reset() for Form

    Learn how to update part of form model, full form model and reset whole form. We have form definetio ...