题目大意:让你在1~n中选择不多于k个数(n,k<=500),保证它们的乘积不能被平方数整除。求选择的方案数

因为质数的平方在500以内的只有8个,所以我们考虑状压

先找出在n以内所有平方数小于等于n的质数,然后我们把它们作为状压的状态

然后要对每个小于n数进行状压,如果它不能被它能被质数的平方整除,那就筛出它所有的在状态内的质因子,大于状态内的质因子我们存到剩余因子的乘积的部分里

比如46,它的状态可以表示成0000 0001 (19,17,13,11,7,5,3,2)  46/2=23,把它存到23的0000 0001状态里

这么做之后,你会惊奇的发现,每个数字只被存到了一个地方,且只被存了一次!

而这也是分组背包可行的关键

下一步就是分组背包了

我们从1遍历到n,遍历所有状态,如果存了,意味着这个状态表示的数可以选一个,就++

然后枚举上一层进行转移即可

细节可以看代码

 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define N 100
#define M 505
#define maxn (1<<8)+5
#define ll long long
#define mod 1000000007
using namespace std; int T,n,m,cnt,K;
ll f[][M][maxn],tmp[M][maxn];
int p[M],ok[M],pr[M],can[M][maxn],use[M];
int a[]={,,,,,,,,,};
vector<int>to[M];
void clr()
{
for(int i=;i<M;i++) to[i].clear();
memset(p,,sizeof(p));
memset(ok,,sizeof(ok));
memset(pr,,sizeof(pr));
memset(can,,sizeof(can));
memset(use,,sizeof(use));
memset(f,,sizeof(f));
cnt=;
}
void get_P()
{
for(int i=;i<=n;i++)
{
if(!use[i]) pr[cnt++]=i;
for(int j=;j<cnt&&i*pr[j]<=n;j++){
use[i*pr[j]]=;
if(i%pr[j]==) break;}
}
for(int i=;i<=n;i++)
{
int x=i,ps=;
for(int j=;j<min(K,);j++)
if(x%(pr[j]*pr[j])==) {
ok[i]=-,p[i]=;
break;
}else if(ok[i]!=-&&x%pr[j]==)
{
p[i]|=(<<j);
x/=pr[j];
}
if(ok[i]!=-)
{
if(x!=) to[x].push_back(i);
else to[i].push_back(i);
}
}
for(int i=;i<=n;i++) //can数组表示i是否存了能用某个二进制质因子表示的数
{
if(ok[i]==-) continue;
for(int j=;j<to[i].size();j++)
can[i][p[to[i][j]]]=;
}
} int main()
{
//freopen("aa.in","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
clr();
K=;
while(K+<=&&a[K+]*a[K+]<=n) K++;
get_P();
int y=,x=;
for(int i=;i<=n;i++){ //分组背包
if(!to[i].size()) continue;
for(int s1=;s1<(<<K);s1++)
for(int j=;j<=m;j++)
f[y][j][s1]=f[x][j][s1];
for(int s1=;s1<(<<K);s1++)
{
if(!can[i][s1]) continue;
f[y][][s1]=(f[y][][s1]+)%mod;
//如果i的状态里有s1,那么说明这个状态表示的数可以直接被选,就++
for(int j=;j<=m;j++)
for(int s2=;s2<(<<K);s2++)
{
if(s1&s2) continue;
f[y][j][s1|s2]+=f[x][j-][s2];
f[y][j][s1|s2]%=mod;
}
}
swap(y,x);
}
ll ans=;
for(int s=;s<(<<K);s++)
for(int j=;j<=m;j++)
ans=(ans+f[x][j][s])%mod;
printf("%lld\n",ans);
}
return ;
}

HDU 6125 Free from square (状压DP+分组背包)的更多相关文章

  1. HDU 6125 Free from square (状压DP+背包)

    题意:问你从 1 - n 至多选 m 个数使得他们的乘积不能整除完全平方数. 析:首先不能整除完全平方数,那么选的数肯定不能是完全平方数,然后选择的数也不能相同的质因子. 对于1-500有的质因子至多 ...

  2. HDU 6125 Free from square 状态压缩DP + 分组背包

    Free from square Problem Description There is a set including all positive integers that are not mor ...

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

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

  4. NOIP模拟 乘积 - 状压dp + 分组背包

    题目大意: 给出n和k,求从小于等于n的数中取出不超过k个,其乘积是无平方因子数的方案数.无平方因子数:不能被质数的平方整除. 题目分析: 10(枚举\(n\le8\)),40(简单状压\(n\le1 ...

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

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

  6. HDU 6125 Free from square(状态压缩+分组背包)

    http://acm.hdu.edu.cn/showproblem.php?pid=6125 题意: 在${1,2,3,...n}$的数中选择1~k个数,使得它们的乘积不能被平方数整除(1除外),计算 ...

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

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

  8. HDU 6149 Valley Numer II 状压DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6149 题意:中文题目 解法:状压DP,dp[i][j]代表前i个低点,当前高点状态为j的方案数,然后枚 ...

  9. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

随机推荐

  1. HDU2149 - Public Sale【巴什博弈】

    虽然不想,但是现实总归是现实,Lele始终没有逃过退学的命运,因为他没有拿到奖学金.现在等待他的,就是像FarmJohn一样的农田生涯.  要种田得有田才行,Lele听说街上正在举行一场别开生面的拍卖 ...

  2. 移植Mplayer到OK6410开发板

    移植Mplayer到OK6410开发板 作者:vasage 项目需要,需要将Mplayer移植到开发板上,所以今天花了一下下午成功移植,其中参考很多文档,后发现许多文档陈旧,些许文档有少量错误,所以这 ...

  3. IDEA解决中文乱码问题

    idea在使用过程中经常会遇到各种乱码问题,网上也有很多解决办法,今天所讲的就是终极解决办法: (1)首先,全局搜索文件 idea64.exe.vmoptions 找到之后,将该行代码复制进去即可   ...

  4. Python Study (05)装饰器

    装饰器(decorator)是一种高级Python语法.装饰器可以对一个函数.方法或者类进行加工.在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一 ...

  5. 再谈p2p投融资真相

    近来亲自调查眼下各类p2p.重度调查对象有:人人贷.陆金所.前金所.开鑫贷.礼德財富.招財宝. 投资的有几个小观念: 首先,大家投资都习惯性的细分政府背景和非政府背景.说句实话,这对一个投资人角度来讲 ...

  6. Constraint.constant动画效果

    在autolayout里改动constant时调用animateWithDuration,发现没有动画效果怎么办?在block里加一句[self.view layoutIfNeeded]就OK了

  7. CSS初步理解

    近期在学习牛腩的时候遇到了网页的制作.挺新奇的.其中涉及到了有关CSS的知识,于是乎自己也就花费两个小时的时间.找了本浅显易懂的书来看了一遍,从宏观上来了解CSS的相关内容.有关CSS的基础知识详见下 ...

  8. Codeforces Round #272 (Div. 2) 题解

    Codeforces Round #272 (Div. 2) A. Dreamoon and Stairs time limit per test 1 second memory limit per ...

  9. Create a Visual C++ Wizard for Visual Studio 2005

    from:http://www.codeguru.com/cpp/v-s/devstudio_macros/customappwizards/article.php/c12775/Create-a-V ...

  10. c6----函数的声明和实现

    // // main.c // 函数的声明和定义 // // Created by xiaomage on 15/6/7. // Copyright (c) 2015年 xiaomage. All r ...