题目大意:

给出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;
}

最新文章

  1. jquery中attr和prop的区别、 什么时候用 attr 什么时候用 prop (转自 芈老头 )
  2. [Tools] 使用XP远程登录Win8系统
  3. java进程性能分析步骤-超越昨天的自己系列(11)
  4. ahjesus 部署lighttpd
  5. 开源文件比较工具:WinMerge、KDiff3、diffuse
  6. C#中动态加载和卸载DLL
  7. NOIP2013 货车运输 LCA倍增+最大生成树
  8. 自己的缺省(sheng)源
  9. 其中 (%{WORD:x_forword}|-) |表示或的意思
  10. uva10341 - solve it (二分查找)
  11. Intellj idea 安装JUnit
  12. 简单了解enum
  13. JFinal配合Shiro权限控制在FreeMarker模板引擎中控制到按钮粒度的使用
  14. java安全入门篇之接口验签
  15. nginx 出现504 Gateway Time-out的解决方法
  16. Flyway数据表迁移框架的使用
  17. 如何在Skyline中加载ArcGISServer发布的WMS和WMTS服务
  18. git开发过程的配置和使用
  19. 【AMQ】之JMS Mesage structure(JMS消息结构)
  20. gitbook的学习

热门文章

  1. 让单选input框,不在被选中,添加disabled即可。输入框input的一些技巧
  2. VUE笔记 - 插值表达式 v-on: / @ 事件绑定 定时器运用
  3. Mongodb总结3-稍微封装一下
  4. Codeforces Round #426 (Div. 1) A.The Meaningless Game (二分+数学)
  5. DB2学习总结(1)——DB2数据库基础入门
  6. Leetcode之Best Time to Buy and Sell Stock
  7. 你说你会C++? —— 智能指针
  8. C#实现人脸识别
  9. tomcat自动URLDecode解码问题(+号变空格)
  10. Go语言实战_自己定义OrderedMap