本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!

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+质因数分解

解题报告:

  这道题的思想很巧妙QAQ

  考虑直接算难以考虑,那么我们从题目给定的规则中可以发现其实,选择了一个数就相当于把这个数的质因子集合选了,因为为了确保第二个人选的和第一个人互质,就不能再选这个质因子。

  考虑一个数最多有一个大于根号$500$的质因子,且可以特殊考虑,而小于等于根号$500$的质因子只有$8$个,所以我们可以使用状压$DP$来统计方案。

  因为小于等于根号$500$的质因子可以通过状压判掉,但是大于根号$500$的部分我们必须想办法解决冲突和重复计算的问题。考虑将所有数包含的质因子集合,和大于根号$500$的质因子(如果没有就是$1$)预处理出来,按大于根号$500$的质因子排序,那么这个质因子相等的区间我们一起处理。

  显然这相等的一整个区间,必须是只放入第一个人或者只放入第二个人或者都不放入,那么就可以DP了:

  $f[s1][s2]$表示全局第一个人选择的集合为$s1$,第二个人选择的集合为$s2$时的方案数,接着把$f$的值赋给$g$,

  $g[0、1][s1][s2]$表示第一个人选择的集合为$s1$,第二个人选择的集合为$s2$,同时当前这个大于根号$500$的质因子放入第一个人/第二个人的方案数。

  做一遍$DP$,最后统计完整个相等的区间时,就赋值回$f$:$f[s1][s2]=g[0][s1][s2]+g[1][s1][s2]-f[s1][s2]$,表示的是两种情况相加,但是因为这个质因子两个都不放的情况算了两次,所以需要减掉一次。

  注意$f$、$g$之间相互转换的时间和条件。

  ps:不含大质因子的时候可以每次都统计一遍答案,因为已经可以用状态来防止非法情况了,无需特别考虑。

//It is made by ljh2000
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <complex>
using namespace std;
typedef long long LL;
const int MAXS = 257;
const int MAXN = 520;
const int end = 256;
int n,prime[12]={2,3,5,7,11,13,17,19};
LL p,f[MAXS][MAXS],g[2][MAXS][MAXS],ans;
//f[s1][s2]表示当前第一个人选的集合为s1,第二个人选的集合为s2的方案数
//g[0][s1][s2],表示对于当前大于根号500质因子相同的一个区间而言的,这个质因子分配给第一个人(或者不分配)的方案数;
//g[1][s1][s2]表示对于第二个人而言的 struct Number{
int S;//包含质因子的状态
int prime;//大于根号500的质因子,没有则是1
}a[MAXN]; inline bool cmp(Number q,Number qq){ return q.prime<qq.prime; } inline int getint(){
int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
} inline void work(){
n=getint(); scanf("%lld",&p); int x;
for(int i=2;i<=n;i++) {
x=i;
for(int j=0;j<8;j++) {
if(x%prime[j]>0) continue;
a[i].S|=(1<<j);
while(x%prime[j]==0) x/=prime[j];
}
a[i].prime=x;
}
sort(a+2,a+n+1,cmp);
f[0][0]=1;
for(int i=2;i<=n;i++) {
if(i==2 || a[i].prime!=a[i-1].prime || a[i].prime==1) {
memcpy(g[0],f,sizeof(f));
memcpy(g[1],f,sizeof(f));
} for(int j=end-1;j>=0;j--)
for(int k=end-1;k>=0;k--) {
if((j&k)>0) continue;//不合法
if((a[i].S&k)==0) //不与第二个人冲突,则可以选入第一个人
g[0][ a[i].S | j ][k]+=g[0][j][k],g[0][ a[i].S | j ][k]%=p;
if((a[i].S&j)==0)
g[1][j][ a[i].S | k ]+=g[1][j][k],g[1][j][ a[i].S | k ]%=p;
} if(i==n || a[i].prime==1 || a[i].prime!=a[i+1].prime) {
for(int j=end-1;j>=0;j--)
for(int k=end-1;k>=0;k--) {
if((j&k)>0) continue;
/*!!!*/
f[j][k]=g[0][j][k]+g[1][j][k]-f[j][k];//去掉重复计算没有选当前这个质因子的情况
}
}
}
for(int i=end-1;i>=0;i--)
for(int j=end-1;j>=0;j--)
if((i&j)==0)
ans+=f[i][j],ans%=p;
ans+=p; ans%=p;
printf("%lld",ans);
} int main()
{
work();
return 0;
}

  

BZOJ4197 / UOJ129 [Noi2015]寿司晚宴的更多相关文章

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

    [BZOJ4197][Noi2015]寿司晚宴 Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴 ...

  2. 【bzoj4197】[Noi2015]寿司晚宴 分解质因数+状态压缩dp

    题目描述 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n−1 种不同的寿司,编号 ...

  3. UOJ129 NOI2015 寿司晚宴 数论、状压DP

    传送门 数论题\(n \leq 500\)肯定是什么暴力算法-- 注意到每一个数\(> \sqrt{n}\)的因子最多只有一个,这意味着\(> \sqrt{n}\)的因子之间是独立的,而只 ...

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

    [UOJ#129][BZOJ4197][Noi2015]寿司晚宴 试题描述 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司 ...

  5. [BZOJ4197][Noi2015]寿司晚宴

    4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 412  Solved: 279[Submit][Status] ...

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

    N^0.5以内的质数只有8个, dp(i, j, k)表示用了前i个大质数(>N^0.5), 2人选的质数(<=N^0.5)集合分别为j, k时的方案数. 转移时考虑当前的大质数p是给哪个 ...

  7. BZOJ_4197_[Noi2015]寿司晚宴_状态压缩动态规划

    BZOJ_4197_[Noi2015]寿司晚宴_状态压缩动态规划 Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被 ...

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

    [NOI2015]寿司晚宴 题目描述 为了庆祝NOI的成功开幕,主办方为大家准备了一场寿司晚宴. 小G和小W作为参加NOI的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了n−1种不同的寿 ...

  9. BZOJ 4197: [Noi2015]寿司晚宴 状态压缩 + 01背包

    4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec  Memory Limit: 512 MB Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿 ...

随机推荐

  1. HashMap和ConcurrentHashMap的区别,HashMap的底层源码。

    Hashmap本质是数组加链表.根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap:在hashMap的基 ...

  2. Json工具类库之Gson实战笔记

    日常接口的数据传输通常使用xml或者json来传递数据,xml较庞大但是描述数据能力十分出众,json数据结构较小而且支持ajax传输,xml在数据传输和解析资源占用都比较逊色于json.因此日常的接 ...

  3. iOS蓝牙接收外设数据自动中断

    一.错误原因 在做iOS设备作为central,与蓝牙外设连接,接收蓝牙外设传输的数据时发生蓝牙中断. 在- (void)centralManager:(CBCentralManager *)cent ...

  4. 转:使用awk命令获取文本的某一行,某一列

    1.打印文件的第一列(域)                 : awk '{print $1}' filename2.打印文件的前两列(域)                 : awk '{print ...

  5. Kafka高可用的保证

    zookeeper作为去中心化的集群模式,消费者需要知道现在那些生产者(对于消费者而言,kafka就是生产者)是可用的.    如果没有zookeeper每次消费者在消费之前都去尝试连接生产者测试下是 ...

  6. when you are old

    When you are old william Butler Yeats When you are old and grey and full of sleep And nodding by the ...

  7. 系统非正常关机启动后出现:an error occurred during the file system

    现象描述: 1.系统ssh登录报Too many open files in system,系统登录不进去,就直接强制关机了,开机后出现(2)的错误: 由于文件描述符用完了,需要把fs.file-ma ...

  8. Python 1 的数据类型

    Python3 中有六个标准的数据类型: Number(数字)String(字符串)List(列表)Tuple(元组)Sets(集合)Dictionary(字典) 1.Number(数字) pytho ...

  9. dom树改变监听

    function unwrap(el, target) { if ( !target ) { target = el.parentNode; } while (el.firstChild) { tar ...

  10. Java生成json

    JSON(JavaScript Object Notation):一种轻量级的数据交换格式: Be JSON:在线JSON校验格式化工具 www.bejson.com 需求:编写代码生成如下的json ...