腾讯消消乐 状压dp加普通dp
2017-06-12 17:48
253 查看
样例说明
对于样例 1 而言,f(1)=1f(1)=1,f(2)=9f(2)=9,f(3)=26f(3)=26,f(4)=24f(4)=24。
对于样例 2,f(1)=0f(1)=0,f(2)=2f(2)=2。
样例输入1
4 1
1 1 1 1
样例输出1
193
样例输入2
2 2
2 3
样例输出2
4
样例输入3
1 233
233
样例输出3
1
首先这种肯定想到递推dp,然后就是如何递推过去,肯定就是dp
=前面所有可以到达的状态和。因为再走一步就可以达到dp
.
如何找到前面所有走一步可以到达当前状态的状态。连续的gcd才是一个块.
用状压dp来分块找到哪些状态可以变为当前的状态 存起来 然后线性dp就好了
刚开始看到这个题一脸蒙蔽 是因为这句话没看懂:注意:一次删除以后,剩下的数会合并成为一个连续区间。
这个其实就是 1001001 这个状态可以由 1000001 这个状态转化而成 也就是1000001加一步可以得到 1001001
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll dp[20][(1<<18)+10]; vector<int> v[(1<<18)+10]; int a[30]; const int mod = 1e9+7; int gcd(int a,int b) { return (b==0)?a:gcd(b,a%b); } int main() { int n,K; scanf("%d%d",&n,&K); for(int i=0;i<n;i++) scanf("%d",&a[i]); int end=(1<<n); for(int st=0;st<end;st++) { for(int j=0;j<n;j++) { if(st&(1<<j)) { int tmp=st^(1<<j); v[st].push_back(tmp); int g=a[j]; for(int k=j+1;k<n;k++) { if(st&(1<<k)) { if((g=gcd(g,a[k]))>=K) tmp^=(1<<k),v[st].push_back(tmp); else break; } } } } } dp[0][0]=1; for(int i=1;i<=n;i++) { for(int j=0;j<end;j++) { for(int k=0;k<v[j].size();k++) { dp[i][j]=dp[i][j]+dp[i-1][v[j][k]]%mod;//从0开始 上一个状态 //加上一个块当前状态是由哪些上一个状态加块得到的,所以只要需要的块加一即可 } } } long long res=0; for(int i=1;i<=n;i++) { res=(res+(ll)i*dp[i][(1<<n)-1]%mod)%mod; } printf("%lld\n",res ); }
相关文章推荐
- 计蒜之道2017F-腾讯消消乐(状压dp)
- 计蒜之道-2017复赛-腾讯消消乐(状压DP)
- 计蒜之道-2017复赛-腾讯消消乐(状压DP)
- 计蒜客 2017 复赛 腾讯消消乐 (状压dp)
- (状压dp)2017 计蒜之道 复赛 F. 腾讯消消乐
- 计蒜之道 2017 程序设计大赛 - 计蒜客 复赛 F 腾讯消消乐 状态压缩dp、枚举+剪枝
- hdu 3001 Travelling (TSP 三进制,状压dp)
- CUGB图论专场:Traveling by Stagecoach 状压DP求最短路中的最小花费时间
- BZOJ 2073 [POI2004]PRZ(状压DP)
- LightOJ1316 A Wedding Party(状压DP)
- Hdu 1074Doing Homework(状压DP)
- bzoj2734 [HNOI2012]集合选数(状压DP)
- BZOJ 1079 着色方案 (状压dp)
- 状压DP LightOJ 1011 1037 状压dp简单题
- HDOJ 5135 Little Zu Chongzhi's Triangles 状压DP
- bzoj 3886: [Usaco2015 Jan]Moovie Mooving 状压dp
- [BZOJ1087][SCOI2005]互不侵犯King解题报告|状压DP
- hdu1565(状压dp)
- vijos1286座位安排(状压dp加组合数加gcd)
- uva_10271 - Chopsticks (普通DP)