NOIP模拟 乘积 - 状压dp + 分组背包
题目大意:
给出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 + 分组背包的更多相关文章
- NOI 2015 寿司晚宴 (状压DP+分组背包)
题目大意:两个人从2~n中随意取几个数(不取也算作一种方案),被一个人取过的数不能被另一个人再取.两个人合法的取法是,其中一个人取的任何数必须与另一个人取的每一个数都互质,求所有合法的方案数 (数据范 ...
- HDU - 6125: Free from square (状压DP+分组背包)
problem:给定N,K.表示你有数1到N,让你最多选择K个数,问有多少种方案,使得选择的数的乘积无平方因子数.N,K<500: solution:显然可以状压DP做,但是500以内的素数还是 ...
- HDU 6125 Free from square (状压DP+分组背包)
题目大意:让你在1~n中选择不多于k个数(n,k<=500),保证它们的乘积不能被平方数整除.求选择的方案数 因为质数的平方在500以内的只有8个,所以我们考虑状压 先找出在n以内所有平方数小于 ...
- 树形DP和状压DP和背包DP
树形DP和状压DP和背包DP 树形\(DP\)和状压\(DP\)虽然在\(NOIp\)中考的不多,但是仍然是一个比较常用的算法,因此学好这两个\(DP\)也是很重要的.而背包\(DP\)虽然以前考的次 ...
- HDU 2923 Relocation(状压dp+01背包)
题目代号:HDU2923 题目链接:http://poj.org/problem?id=2923 Relocation Time Limit: 1000MS Memory Limit: 65536K ...
- [CSP-S模拟测试]:点亮(状压DP+树上背包DP)
题目传送门(内部题121) 输入格式 第一行,一个正整数$n$. 第二行,$n-1$个正整数$p_2,p_3,...,p_n$.保证$p_u$是在$1$到$u-1$中等概率随机选取的. 接下来$n$行 ...
- hdu 6125 状压dp+分组
一道玄学题... 其实一开始想的是对的,优化一下就好了 首先我们会发现,乘积不能被完全平方数整除等价于所有因子的每个质因子个数和都至多为1 可是500以内的质数很多,全找出来会爆炸的 可我们会发现,如 ...
- poj 2923 状压dp+01背包
好牛b的思路 题意:一系列物品,用二辆车运送,求运送完所需的最小次数,两辆车必须一起走 解法为状态压缩DP+背包,本题的解题思路是先枚举选择若干个时的状态,总状态量为1<<n,判断这些状态 ...
- BZOJ 4145: [AMPPZ2014]The Prices( 状压dp + 01背包 )
我自己只能想出O( n*3^m )的做法....肯定会T O( nm*2^m )做法: dp( x, s ) 表示考虑了前 x 个商店, 已买的东西的集合为s. 考虑转移 : 先假设我们到第x个商店去 ...
随机推荐
- Mongodb总结6-数据库启动、停止、备份等命令
#启动Mongodb默认启动,需要在/data/db,Windows下对应的目录是Mongod.exe所在磁盘分区的根目录,例如Mongodb存放在D:/Mongodb,那么对应的路径就是D:/dat ...
- C#中防止程序多次运行
C#中如何防止程序多次运行?只要在程序入口点函数Main()中的开始部分添加如注释部分的代码,就能快捷实现. 示例代码如下: using System; using System.Collecti ...
- Altium Designer如何设置pcb尺寸
- JS实现跑马灯效果(鼠标滑入可暂停,离开继续跑)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- iOS_02_什么是ios开发
什么是ios开发? * 已知:ios是iphone,ipad等手持设备操作系统. * ios开发就是开发运行在ios系统上的应用或者游戏软件,比如手机QQ,微博或者游戏,说白了,就是开发手机软件:当然 ...
- 前端实时消息提示的效果-websocket长轮询
WebSocket是html5新增加的特性之一,可以实现客户端和服务器彼此之间相互通信,也可以实现跨域通信,目前大部分主流浏览器都支持,iE浏览器需要10版本以上. 需求:公司项目有一个报警模块,当后 ...
- [PostgreSQL] Use Foreign Keys to Ensure Data Integrity in Postgres
Every movie needs a director and every rented movie needs to exist in the store. How do we make sure ...
- icvPrecalculate
/* *icvPrecalculate *作用:计算特征值,并排序 *详细来说也就是依据训练样本信息和haar特征信息,在函数内部引用icvGetTrainingDataCallback来 *分批计算 ...
- SDL2源码分析1:初始化(SDL_Init())
===================================================== SDL源码分析系列文章列表: SDL2源码分析1:初始化(SDL_Init()) SDL2源 ...
- 【计算机】基本概念的理解 —— 沙盒(sandbox)、交互式计算/编程/应用
web scraper:网络铲: scraper:n. 刮刀:铲土机:守财奴: 1. 交互式计算/编程/应用(interactive computing/application/programming ...