BZOJ4197: [Noi2015]寿司晚宴 状压DP
2017-04-11 13:54
323 查看
题意:把2~n这些数分成两个可空集合,要求两个集合中任取一对数都必须互质,求方案数
2≤n≤500
比较显然的是可以把每个数分解质因数,相当于两个集合中不能存在同一质因数。
但是质数个数可能很多,并不好设状态。
注意到每个数中最多只有一个大于等于根号n的质因子,而小于根号n的质数只有8个,那么将所有数按照大质因子分类,规定每一类最多只能被一个集合选,就可以把前八个质数状压来表示状态了。
注意没有大质因子的数每个都要单成一类而不是放在同一类,因为互相并不影响。
那么可以考虑一下如何转移,设f[i][j] 表示当前已经有多少种方案使得第一个集合状态为i,第二个集合状态为j。对于一个新的类,分别枚举把这个类给第一个集合与给第二个集合两种情况。具体的,若给第一个集合,先令g[i][j]=f[i][j], 再枚举这一类中的每个元素进行g[i|x][j]+=g[i][j] 的转移,给第二个集合同理。最后,由于两种转移是平行的,因此新的f[i][j]是将两者的g[i][j]相加,又由于两个都不给的情况在二者中都出现了,因此还要再减去原来的f[i][j]。 最后累加所有i&j==0的f[i][j]即可。
代码:
2≤n≤500
比较显然的是可以把每个数分解质因数,相当于两个集合中不能存在同一质因数。
但是质数个数可能很多,并不好设状态。
注意到每个数中最多只有一个大于等于根号n的质因子,而小于根号n的质数只有8个,那么将所有数按照大质因子分类,规定每一类最多只能被一个集合选,就可以把前八个质数状压来表示状态了。
注意没有大质因子的数每个都要单成一类而不是放在同一类,因为互相并不影响。
那么可以考虑一下如何转移,设f[i][j] 表示当前已经有多少种方案使得第一个集合状态为i,第二个集合状态为j。对于一个新的类,分别枚举把这个类给第一个集合与给第二个集合两种情况。具体的,若给第一个集合,先令g[i][j]=f[i][j], 再枚举这一类中的每个元素进行g[i|x][j]+=g[i][j] 的转移,给第二个集合同理。最后,由于两种转移是平行的,因此新的f[i][j]是将两者的g[i][j]相加,又由于两个都不给的情况在二者中都出现了,因此还要再减去原来的f[i][j]。 最后累加所有i&j==0的f[i][j]即可。
代码:
#include<cstdio> #include<vector> #include<cstring> using namespace std; typedef unsigned int u; int pri[]={2,3,5,7,11,13,17,19}; vector<u> v[501]; int n,p; int f[1<<8][1<<8],g1[1<<8][1<<8],g2[1<<8][1<<8]; u maxn=(1<<8)-1; int main() { scanf("%d%d",&n,&p); for(int i=2;i<=n;++i) { u k=0; int x=i; for(int j=0;j<8;++j) { while(x%pri[j]==0) { k|=(1u<<j); x/=pri[j]; } } if(x==1) v[i].push_back(k); else v[x].push_back(k); } f[0][0]=1; for(int i=1;i<=n;++i) if(!v[i].empty()) { memcpy(g1,f,sizeof g1); memcpy(g2,f,sizeof g2); for(vector<u>::iterator __it=v[i].begin(),__end=v[i].end();__it!=__end;++__it) { u x=*__it; for(u j=maxn;~j;--j) for(u k=maxn;~k;--k) { (g1[j|x][k]+=g1[j][k])%=p; (g2[j][k|x]+=g2[j][k])%=p; } } for(u j=0;j<=maxn;++j) for(u k=0;k<=maxn;++k) f[j][k]=((u)g1[j][k]+g2[j][k]+p-f[j][k])%p; } int ans=0; for(u i=0;i<=maxn;++i) for(u j=0;j<=maxn;++j) if((i&j)==0) (ans+=f[i][j])%=p; printf("%d\n",ans); return 0; }
相关文章推荐
- [NOI2015][BZOJ4197][状压DP]寿司晚宴
- bzoj4197 [NOI2015] [状压dp] 寿司晚宴
- bzoj4197[Noi2015]寿司晚宴 [状压DP]
- 【NOI2015】【bzoj4197】【状压DP】【滚动数组】寿司晚宴
- BZOJ4197 [Noi2015]寿司晚宴 【状压dp】
- [NOI2015][bzoj4197] 寿司晚宴 [状压dp+质因数]
- 【BZOJ4197】[Noi2015]寿司晚宴【状压DP】【背包】
- [BZOJ4197][UOJ129][Noi2015]寿司晚宴(状压DP)
- [BZOJ4197][Noi2015]寿司晚宴
- BZOJ4197 [Noi2015]寿司晚宴
- bzoj4197 [Noi2015]寿司晚宴
- bzoj4197 [Noi2015]寿司晚宴
- 【bzoj4197】[Noi2015]寿司晚宴 dp
- 【bzoj4197】[Noi2015]寿司晚宴
- BZOJ 4197: [Noi2015]寿司晚宴 状压dp 质因数分解
- 【bzoj4197】[Noi2015]寿司晚宴 分解质因数+状态压缩dp
- Bzoj4197: [Noi2015]寿司晚宴
- [bzoj4197][Noi2015]寿司晚宴【dp】
- bzoj 4197: [Noi2015]寿司晚宴【状压dp】
- BZOJ4197 / UOJ129 [Noi2015]寿司晚宴