[ZOJ 3662] Math Magic (动态规划+状态压缩)

先贴代码,晚上回去说

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <map>
 6 #include <iterator>
 7 #include <vector>
 8 using namespace std;
 9 typedef long long LL;
10
11 int n,m,k;
12 int p[1000],h[1000],w[1000],v[1000],ptr;
13 int dp[111][1100][1<<5];
14 const int MOD = 1000000007;
15
16 void prime_factor(int x){
17     for(int i=2;i*i<=x;i++){
18         while( x%i==0 ){
19             p[i]++;
20             x /= i;
21         }
22     }
23     if( x!=1 ) p[x] = 1;
24 }
25
26 void handle(int x){
27     w[++ptr] = x;
28     for(int i=2;i*i<=x;i++){
29         int t = 0;
30         while( x%i==0 ){
31             t ++;
32             x /= i;
33         }
34         if( t&&t==p[i] ) v[ptr] |= (1<<(h[i]-1));
35     }
36     if( x!=1&&p[x]==1 ) v[ptr] |= (1<<(h[x]-1));
37 }
38
39 int main(){
40     while(scanf("%d%d%d",&n,&m,&k)!=EOF){
41         ptr = 0;
42         memset(p,0,sizeof(p));
43         memset(w,0,sizeof(w));
44         memset(v,0,sizeof(v));
45         memset(h,0,sizeof(h));
46         prime_factor(m);
47         int sn = 0;
48         for(int i=0;i<1000;i++){
49             if( p[i] ) {
50                 h[i] = ++sn;
51             }
52         }
53         for(int i=2;i*i<=m;i++){
54             if( m%i==0 ) {
55                 handle(i);
56                 if( i*i!=m ) handle(m/i);
57             }
58         }
59         handle(1);
60         if(m!=1) handle(m);
61         memset(dp,0,sizeof(dp));
62         dp[0][0][0] = 1;
63         for(int j=1;j<=k;j++){
64             for(int i=1;i<=ptr;i++){
65                 for(int k=0;k<=n;k++){
66                     for(int mask=0;mask<(1<<sn);mask++){
67                         if( k+w[i]<=n&&(mask|v[i])<(1<<sn) ){
68                             dp[j][k+w[i]][mask|v[i]] = (dp[j][k+w[i]][mask|v[i]]+dp[j-1][k][mask])%MOD;
69                         }
70                     }
71                 }
72             }
73         }
74         printf("%d\n",dp[k][n][(1<<sn)-1]);
75     }
76     return 0;
77 }
时间: 2024-10-20 21:21:08

[ZOJ 3662] Math Magic (动态规划+状态压缩)的相关文章

D - Doing Homework HDU1074 ( 动态规划 + 状态压缩 )

D - Doing Homework Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1074 Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him

ACM学习历程—HDU1584 蜘蛛牌(动态规划 &amp;&amp; 状态压缩)

Description 蜘蛛牌是windows xp操作系统自带的一款纸牌游戏,游戏规则是这样的:只能将牌拖到比她大一的牌上面(A最小,K最大),如果拖动的牌上有按顺序排好的牌时,那么这些牌也跟着一起移动,游戏的目的是将所有的牌按同一花色从小到大排好,为了简单起见,我们的游戏只有同一花色的10张牌,从A到10,且随机的在一行上展开,编号从1到10,把第i号上的牌移到第j号牌上,移动距离为abs(i-j),现在你要做的是求出完成游戏的最小移动距离. Input 第一个输入数据是T,表示数据的组数.

ZOJ 3802 Easy 2048 Again ( 状态压缩 )

题目链接~~> 做题感悟:这题很经典 ,需要模拟一下找规律,还是那句话遇到题自己应该手动推一下. 解题思路: 这题如果手动推几组数据的话就应该发现 ,如果放进队列的元素是递减的话,这样才可以连续合并,如果队列中有 a  ,b , a < b 那么 a 前面的必定不会与 b 经过合并再合并,因为越合并越大,so ~> 队列中最多才存 12 个数,可以用状态压缩压缩一下.注意要用滚动数组,不用可能超时. 代码: #include<iostream> #include<sst

[POJ 2923] Relocation (动态规划 状态压缩)

题目链接:http://poj.org/problem?id=2923 题目的大概意思是,有两辆车a和b,a车的最大承重为A,b车的最大承重为B.有n个家具需要从一个地方搬运到另一个地方,两辆车同时开,问最少需要搬运几次? 我先想的是我由A车开始搬,搬运能装的最大的家具总重,然后状态压缩记录下搬运了哪些,然后再由B车搬运,状态压缩记录搬运了哪些.以此类推,直到状态满了. 以上方法TLE 然后,实在想不出来了,看了题解:http://blog.csdn.net/woshi250hua/articl

zoj 3471 Most Powerful(状态压缩dp)

Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way every two at

3.4 熟练掌握动态规划——状态压缩DP

从旅行商问题说起—— 给定一个图,n个节点(n<=15),求从a节点出发,经历每个节点仅一次,最后回到a,需要的最短时间. 分析: 设定状态S代表当前已经走过的城市的集合,显然,S<=(1<<n)-1. dp[k][s]——从a走到k,已经经历过的节点集合为s,按照规则走回a所需要的最短时间. 初始化:dp[k][s]=-1 int DP(int K,int S) { if (dp[K][S]!=-1) { return dp[K][S]; } if (K==a &&

【POJ 1170】 Shopping Offers [动态规划 状态压缩 背包][离散化]

POJ - 1170 Shopping Offers 放假打题 sufu 看完题我是懵比的 这....  emmmmm   瓜想了半个小时之后我选择狗带 然后点开链接 装压+dp!!!!哦!!!!!!巧妙!!!! 就先把目标状态还有各个优惠的状态处理好 然后就是一个完全背包处理用优惠 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int S=100+5,N=10,P=10000+5,C=1000+5; 4 int sale[S

奇妙的算法—状态压缩动态规划

华电北风吹 天津大学认知计算与应用重点实验室 日期:2015/8/27 由于代码未调试完全正确论文草稿呈现 poj上一道需要用到状态压缩动态规划,链接http://poj.org/problem?id=3254 网上看到有很多人写出了代码,参考了一个带备忘的自顶向下的动态规划解法,自己写了一个有底向上的动态规划解法 有底向上: #include<iostream> #include<math.h> #include<ostream> #include<fstrea

插头与轮廓线与基于连通性状态压缩的动态规划

问题定义 什么是插头DP 在一个n*m的棋盘上(n与m很小),求: 有多少种不同的回路数 用1条回路经过所有点的方案数 用1条回路经过部分点的方案数 1条路径上的权值和最大 的这一类问题,通常可以用插头DP来解决. 这类问题通常很明显,但代码量大又容易出错,有时TLE有时MLE. 什么是基于状态压缩的动态规划 基于状态压缩的动态规划问题是一类以集合信息为状态且状态总数为指数级的特殊的动态规划问题. 在状态压缩的基础上,有一类问题的状态中必须要记录若干个元素的连通情况,我们称这样的问题为基于连通性