【NOI2015】【bzoj4197】【状压DP】【滚动数组】寿司晚宴
来源:互联网 发布:次日留存算法 编辑:程序博客网 时间:2024/04/29 02:44
Description
为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴。小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴。
在晚宴上,主办方为大家提供了 n−1 种不同的寿司,编号 1,2,3,…,n−1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n)。
现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当:小 G 品尝的寿司种类中存在一种美味度为 x 的寿司,小 W 品尝的寿司中存在一种美味度为 y 的寿司,而 x 与 y 不互质。
现在小 G 和小 W 希望统计一共有多少种和谐的品尝寿司的方案(对给定的正整数 p 取模)。注意一个人可以不吃任何寿司。Input
输入文件的第 1 行包含 2 个正整数 n,p,中间用单个空格隔开,表示共有 n 种寿司,最终和谐的方案数要对 p 取模。
Output
输出一行包含 1 个整数,表示所求的方案模 p 的结果。
Sample Input
3 10000
Sample Output
9
HINT
2≤n≤500
0< p≤1000000000
状态压缩DP,我写的
然后大概说一下怎么DP
我们选取一个数,实际上就是选它的质因数,而500以内质数有95个明显无法装压,但我们还可以发现,500以内每个数大于
我们建立两个数组f[k][i][j]表示考虑前k个数,A的状态为i,B的状态为j有多少个情况,dp[0/1][k][i][j]表示正在考虑第k个数,A/B拿走第k个数,拿走后A状态为i,B为j
然后转移方程可以列出:
dp[0][k][i|p(k)][j]=f[k-1][i|p(k)][j]+dp[0][k][i][j]
dp[1][k][i][j|p(k)]=f[k-1][i][j|p(k)]+dp[1][k][i][j]
f[k][i][j]=dp[0][k][i][j]+dp[1][k][i][j]-f[k-1][i][j]
但是数组开不下,我们就可以滚动,这时才有了我一直没看懂的转移方程
dp[0][i|p(k)][j]=dp[0][i|p(k)][j]+dp[0][i][j]
dp[1][i][j|p(k)]=dp[1][i][j|p(k)]+dp[1][i][j]
f[i][j]=dp[0][i][j]+dp[1][i][j]-f[i][j]
然后我们先处理前面全部属于那8个质数的,再一个一个大质数的枚举,处理就可以了
程序如下:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<set>#include<map>#include<queue>#include<algorithm>#include<vector>#include<cstdlib>#include<cmath>#include<ctime>#include<stack>#define INF 2100000000#define ll long long#define clr(x) memset(x,0,sizeof(x))#define clrmax(x) memset(x,127,sizeof(x))using namespace std;inline int read(){ char c; int ret=0; while(!(c>='0'&&c<='9')) c=getchar(); while(c>='0'&&c<='9') { ret=(c-'0')+(ret<<1)+(ret<<3); c=getchar(); } return ret;}#define M 500#define N (1<<8)int f[N][N],dp[2][N][N],n,P,t;const int pri[]={2,3,5,7,11,13,17,19};struct node{ int x,num; node(int x=0,int num=0):x(x),num(num){}}a[M];#define x(y) a[y].x#define num(x) a[x].numbool com(node a,node b){ return a.x<b.x;}void add(int x){ int temp=0; for(int i=0;i<8;i++) while(x%pri[i]==0) { x/=pri[i]; temp|=1<<i; } a[++t]=node(x,temp);}void DP(){ f[0][0]=1; for(int l=1,r;l<=t;l=r+1) { for(r=l;x(r+1)==x(r)&&x(r)!=1;r++); memcpy(dp[0],f,sizeof(f));memcpy(dp[1],f,sizeof(f)); for(int k=l;k<=r;k++) { for(int i=255;~i;i--) { int now=255^i; for(int j=now;;j=(j-1)&now) { if((j&num(k))==0) dp[0][i|num(k)][j]=(dp[0][i|num(k)][j]+dp[0][i][j])%P; if((i&num(k))==0) dp[1][i][j|num(k)]=(dp[1][i][j|num(k)]+dp[1][i][j])%P; if(!j)break; } } } for(int i=0;i<=255;i++) for(int j=0;j<=255;j++) f[i][j]=((dp[0][i][j]+dp[1][i][j]-f[i][j])%P+P)%P; } int ans=0; for(int i=0;i<=255;i++) { int now=255^i; for(int j=now;;j=(j-1)&now) { ans=(ans+f[i][j])%P; if(!j)break; } } printf("%d",ans);}int main(){ //freopen("in.txt","r",stdin); n=read();P=read(); for(int i=2;i<=n;i++) add(i); sort(a+1,a+t+1,com); DP(); return 0;}
大概就是这个样子,如果有什么问题,或错误,请在评论区提出,谢谢。
- 【NOI2015】【bzoj4197】【状压DP】【滚动数组】寿司晚宴
- 【bzoj4197】[Noi2015]寿司晚宴 状压DP
- 【BZOJ4197】[Noi2015]寿司晚宴【状压DP】【背包】
- [NOI2015][BZOJ4197][状压DP]寿司晚宴
- bzoj4197[Noi2015]寿司晚宴 [状压DP]
- bzoj4197 [NOI2015] [状压dp] 寿司晚宴
- BZOJ4197: [Noi2015]寿司晚宴 状压DP
- 【bzoj4197】[Noi2015]寿司晚宴 dp
- BZOJ4197 [Noi2015]寿司晚宴
- bzoj4197 [Noi2015]寿司晚宴
- 【bzoj4197】[Noi2015]寿司晚宴
- Bzoj4197: [Noi2015]寿司晚宴
- 【bzoj4197】【NOI2015】寿司晚宴
- 【NOI2015】【寿司晚宴】【状压DP】
- NOI2015 寿司晚宴 状压DP
- bzoj 4197: [Noi2015]寿司晚宴 状压dp
- [BZOJ 4197][Noi2015]寿司晚宴:状压DP
- BZOJ 4197([Noi2015]寿司晚宴-状压dp)
- Html5 前端 网页滚动条样式的设置
- CSS基础学习5-CSS设置链接
- Html学习总结(2)——Html页面head标签元素的意义和应用场景
- 第七周项目3-负数把正数赶出队列
- https查看证书
- 【NOI2015】【bzoj4197】【状压DP】【滚动数组】寿司晚宴
- AHRS(航姿参考系统)和IMU(惯性测量单元)的区别
- Cesium BaseLayerPicker
- RGB、YUV和YCbCr
- svn生成patch与应用patch
- 第八周 项目一——建立顺序串的算法库
- windows下python绿色安装
- 浅谈web应用的负载均衡、集群、高可用(HA)解决方案
- linux 查看所在服务器硬件,软件情况