【BZOJ4197】[Noi2015]寿司晚宴 状压DP+分解质因数

【BZOJ4197】[Noi2015]寿司晚宴

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

题解:我们考虑每个素数,它要么在A中,要么在B中,要么都不在。我们定义<sqrt(500)(更具体的说是<=19,因为23*29>500)的质数为小质数,其余的为大质数,则2-n中的任意一个数都可以表示成1(或0)个大质数*若干个小质数。因此我们可以状压小质数,枚举大质数。

用g[0或1][x][y]表示当前的大质数在A或B中,A的小质数状态为x,B的小质数状态为y的方案数。我们预处理出对于每个大质数,可以和它搭配的 小质数组 有哪些(其实就是枚举一个大质数p的所有倍数,将所有倍数都分解质因数)。如果当前这个数要被A选,相当于A既要选这个大质数也要选这个 小质数组 ,并且B既不能选这个大质数也不能选这个 小质数组 中的任一个质数。我们设这个 小质数组 的状态为S,得到DP方程:

g[0][x|S][y]=g[0][x|S][y]+g[0][x][y]
g[1][x][y|S]=g[1][x][y|S]+g[1][x][y]

我们用f[x][y]统计答案,但是发现存在重复的情况。你可以理解为虽然这个数被A抢走了,使得B不能选这个数,但是A也不想选这个数。或者这个数被B抢走了,但是B也不想选。那么重复的方案数是多少呢?就是之前的f[x][y]。所以新的f[x][y]=g[0][x][y]+g[1][x][y]-旧的f[x][y]。

同时,对于不包含大质数的数,要特殊处理。对于不同的大质数,用乘法原则统计答案(因为A可以把好多大质数都抢走);对于不同的小质数选择方法,用加法原则统计答案(小质数不能既给A又给B);DP的时候要时刻满足x&y==0。(以上都是只有本蒟蒻才不明白的地方。)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
int n,mod,ans;
int f[1<<8][1<<8],g[2][1<<8][1<<8];
int p2[510];
int pri[]={2,3,5,7,11,13,17,19};
vector<int> v[510];
int getpri(int x)
{
	int i,ret=0;
	for(i=0;i<8;i++)
	{
		if(x%pri[i]==0)
		{
			ret|=(1<<i);
			while(x%pri[i]==0)	x/=pri[i];
		}
	}
	v[x].push_back(ret);
}
int main()
{
	scanf("%d%d",&n,&mod);
	int i,j,x,y;
	for(i=2;i<=n;i++)	getpri(i);
	f[0][0]=1;
	for(j=0;j<v[1].size();j++)
	{
		for(x=(1<<8)-1;~x;x--)
		{
			for(y=(1<<8)-1;~y;y--)	if(!(x&y))
			{
				if(!(y&v[1][j]))	f[x|v[1][j]][y]=(f[x|v[1][j]][y]+f[x][y])%mod;
				if(!(x&v[1][j]))	f[x][y|v[1][j]]=(f[x][y|v[1][j]]+f[x][y])%mod;
			}
		}
	}
	for(i=23;i<=n;i++)
	{
		if(!v[i].size())	continue;
		for(x=0;x<(1<<8);x++)	for(y=0;y<(1<<8);y++)	if(!(x&y))	g[0][x][y]=g[1][x][y]=f[x][y];
		for(j=0;j<v[i].size();j++)
		{
			for(x=(1<<8)-1;~x;x--)
			{
				for(y=(1<<8)-1;~y;y--)	if(!(x&y))
				{
					if(!(y&v[i][j]))	g[0][x|v[i][j]][y]=(g[0][x|v[i][j]][y]+g[0][x][y])%mod;
					if(!(x&v[i][j]))	g[1][x][y|v[i][j]]=(g[1][x][y|v[i][j]]+g[1][x][y])%mod;
				}
			}
		}
		for(x=0;x<(1<<8);x++)	for(y=0;y<(1<<8);y++)	f[x][y]=((g[0][x][y]+g[1][x][y]-f[x][y])%mod+mod)%mod;
	}
	for(x=0;x<(1<<8);x++)	for(y=0;y<(1<<8);y++)	ans=(ans+f[x][y])%mod;
	printf("%d",ans);
	return 0;
}
时间: 2024-10-26 09:51:36

【BZOJ4197】[Noi2015]寿司晚宴 状压DP+分解质因数的相关文章

BZOJ 4197 NOI 2015 寿司晚宴 状压DP

4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 694  Solved: 440[Submit][Status][Discuss] Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n?1 种不同的寿司,编号 1,2,3,-,n?1,其中第 i 种寿司的美味度为 i+1 (即

bzoj4197 [Noi2015]寿司晚宴

Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n?1 种不同的寿司,编号 1,2,3,-,n?1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n). 现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当:小 G 品尝的寿司种类中存在一种美味度为 x 的寿司,小 W 品尝的寿司中存在一种美味度为 y

[UOJ#129][BZOJ4197][Noi2015]寿司晚宴

试题描述 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n?1 种不同的寿司,编号 1,2,3,-,n?1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n). 现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当:小 G 品尝的寿司种类中存在一种美味度为 x 的寿司,小 W 品尝的寿司中存在一种美味度为 y 的寿司,而

状压DP --- [NOI2015]寿司晚宴

[NOI2015]寿司晚宴 题目描述 为了庆祝NOI的成功开幕,主办方为大家准备了一场寿司晚宴. 小G和小W作为参加NOI的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了n?1种不同的寿司,编号1,2,3,?,n-1,其中第种寿司的美味度为i+1(即寿司的美味度为从2到n). 现在小G和小W希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当: 小G品尝的寿司种类中存在一种美味度为x的寿司,小W品尝的寿司中存在一种美味度为y的寿司,而x与y不互质. 现在小G和小W希

【NOI2015】寿司晚会 题解(状压DP)

[问题描述] 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n?1 种不同的寿司,编号 1,2,3,?, n?1, 其中第 i 种寿司的美味度为 i+1  (即寿司的美味度为从 2 到 n ). 现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案 为不和谐的当且仅当:小 G 品尝的寿司种类中存在一种美味度为 x 的寿司,小 W 品尝的寿司中存在一种美味度为 y

N - 寿司晚宴 HYSBZ - 4197 状压dp

N - 寿司晚宴 HYSBZ - 4197 推荐题解 这个题目我觉得还是很难的,借助题解写出来的,题解还看了很久,现在还是不是很理解. 首先这个数比较大有500,如果直接就像这个题目S - Query on a tree 这样写就超时了,而且也存不下这么大的数. 因为这个500以内的质数太多了,然后看了这么多题解你会发现根号500以内的质数只有8个. 而每一个数大于根号500的质数最多一个,所以我们可以先讨论这个小于根号500的质数,然后再判断这个大于根号500的质数. 讨论完之后再判断这个大于

BZOJ 4197: [Noi2015]寿司晚宴( dp )

N^0.5以内的质数只有8个, dp(i, j, k)表示用了前i个大质数(>N^0.5), 2人选的质数(<=N^0.5)集合分别为j, k时的方案数. 转移时考虑当前的大质数p是给哪个人即可. 时间复杂度O(N*2^16) ----------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm&

[BZOJ]4197: [Noi2015]寿司晚宴

Time Limit: 10 Sec  Memory Limit: 512 MB Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n?1 种不同的寿司,编号 1,2,3,-,n?1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n). 现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当:小 G 品尝

POJ 1038 状压DP

一个公司生产一种2*3规模的芯片,但是原材料上面有一些地方是不能用来当作芯片材料的,给出原料大小,及上面不能做原料的点,问你怎么分解,可以使生成芯片最大化. 对M进行三进制状压 last数组存储第i-1行和i-2行状态,cur数组存储i行和i-1行状态 cur[k]=2; // 本行k位置和上行k位置都不可用 cur[k]=1; // 本行k位置可用,上行k位置不可用 cur[k]=0; // 本行和上行位置k均可用 必须用滚动数组,否则爆内存 #include "stdio.h" #