HDU 6125 Free from square (状压DP+分组背包)
题目大意:让你在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+分组背包)的更多相关文章
- HDU 6125 Free from square (状压DP+背包)
题意:问你从 1 - n 至多选 m 个数使得他们的乘积不能整除完全平方数. 析:首先不能整除完全平方数,那么选的数肯定不能是完全平方数,然后选择的数也不能相同的质因子. 对于1-500有的质因子至多 ...
- HDU 6125 Free from square 状态压缩DP + 分组背包
Free from square Problem Description There is a set including all positive integers that are not mor ...
- NOI 2015 寿司晚宴 (状压DP+分组背包)
题目大意:两个人从2~n中随意取几个数(不取也算作一种方案),被一个人取过的数不能被另一个人再取.两个人合法的取法是,其中一个人取的任何数必须与另一个人取的每一个数都互质,求所有合法的方案数 (数据范 ...
- NOIP模拟 乘积 - 状压dp + 分组背包
题目大意: 给出n和k,求从小于等于n的数中取出不超过k个,其乘积是无平方因子数的方案数.无平方因子数:不能被质数的平方整除. 题目分析: 10(枚举\(n\le8\)),40(简单状压\(n\le1 ...
- HDU - 6125: Free from square (状压DP+分组背包)
problem:给定N,K.表示你有数1到N,让你最多选择K个数,问有多少种方案,使得选择的数的乘积无平方因子数.N,K<500: solution:显然可以状压DP做,但是500以内的素数还是 ...
- HDU 6125 Free from square(状态压缩+分组背包)
http://acm.hdu.edu.cn/showproblem.php?pid=6125 题意: 在${1,2,3,...n}$的数中选择1~k个数,使得它们的乘积不能被平方数整除(1除外),计算 ...
- 树形DP和状压DP和背包DP
树形DP和状压DP和背包DP 树形\(DP\)和状压\(DP\)虽然在\(NOIp\)中考的不多,但是仍然是一个比较常用的算法,因此学好这两个\(DP\)也是很重要的.而背包\(DP\)虽然以前考的次 ...
- HDU 6149 Valley Numer II 状压DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6149 题意:中文题目 解法:状压DP,dp[i][j]代表前i个低点,当前高点状态为j的方案数,然后枚 ...
- HDU 5434 Peace small elephant 状压dp+矩阵快速幂
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: ...
随机推荐
- HDU-1695 GCD(求一个区间内与一个数互质的个数)
题意: 给你一个T,是样例的个数,接下来是五个数l1,r1,l2,r2,k 前四个数代表两个区间(l1,r1),(l2,r2)这个题l1=1,l2=1; 取x1属于(1,r1),x2属于(1,r2) ...
- 训练1-A
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? Input 输入中含有一些数据,分别是成对出现的花布条和 ...
- SendKeys发送组合键
使用: using System.Windows.Forms;//添加命名空间引用 { SendKeys.SendWait("{DOWN}"); ppt.ppt_sendkey(& ...
- base64格式文件下载方法
下载图片时,接口返回的地址是base64格式的文件数据,因为页面需要把base64格式的数据转换为文件,再进行下载: 解决方案: 下载按钮: <el-button type="defa ...
- 转载:Java编程风格与命名规范整理
转载自:传送门 不想复制,点进去看喽23333333
- POJ 1944
明天补上... 这道题的思路确实很精致.考虑到连的边肯定不会是一个环,所以至少有一个断点.于是,可以枚举这个断点.断点一确定,那么连边的走向也就确定了.用D[i]表示由i开始可以到达的最远点即可.对于 ...
- iOS中的crash防护(二)KVC造成的crash
接上篇< iOS中的crash防护(一)unrecognized selector sent to instance> 我们攻克了找不到方法实现的crash,这一篇我这里主要分析一下在 ...
- android Service中多线程交互
android 的service和activity是执行在UI主线程的. 在android线程中,仅仅有主线程即UI线程有自己的默认的消息队列.子线程须要创建自己的消息队列.并把消息发给队列,并循环起 ...
- Codeforces Round #168 (Div. 2)---A. Lights Out
Lights Out time limit per test 2 seconds memory limit per test 256 megabytes input standard input ou ...
- yarn架构——本质上是在做解耦 将资源分配和应用程序状态监控两个功能职责分离为RM和AM
Hadoop YARN架构解读 原Mapreduce架构 原理架构图如下: 图 1.Hadoop 原 MapReduce 架构 原 MapReduce 程序的流程:首先用户程序 (JobClient) ...