解:发现每个质数只能属于一个人,于是想到每个质数有三种情况:属于a,属于b,都不属于。

然后考虑状压每个人的质数集合,可以得到30分。

转移就是外层枚举每个数,内层枚举每个人的状态,然后看能否转移。能转移就转移。

考虑优化:有个套路是大于√的质数最多只有一个。于是单独考虑那些,先把不含那些的转移出来放到数组f中。

然后每次外层枚举一个质数,中层枚举它的倍数,内层枚举两个人的状态。

每个质数可以属于a或者属于b或者都不属于。考虑到转移属于a的时候我们不可避免的会算到都不属于(除非再开一维记录),于是容斥一波。

属于a和属于b因为要分开转移多次(中层枚举倍数),于是用g,h数组分别转移。

最后f = g + h - f(容斥掉都不属于)。

其实感觉多开一维好想一点......。

 #include <bits/stdc++.h>

 typedef long long LL;
const int N = , M = ; int n, sta[N], p[N], top, last[N], id[N], stk[N], tp;
LL f[][M][M], g[][M][M], MO, h[][M][M], F[M][M];
bool vis[N]; inline void Add(LL &a, const LL &b) {
a += b;
while(a >= MO) a -= MO;
while(a < ) a += MO;
return;
} inline void getp(int n) {
for(int i = ; i <= n; i++) {
if(!vis[i]) {
p[++top] = i;
id[i] = top;
last[i] = i;
}
for(int j = ; j <= top && i * p[j] <= n; j++) {
vis[i * p[j]] = ;
last[i * p[j]] = p[j];
if(i % p[j] == ) break;
}
}
return;
} int main() { //freopen("in.in", "r", stdin); scanf("%d%lld", &n, &MO);
getp(n); int m = ;
while(m < top && p[m + ] <= ) m++;
int lm = << m; for(int i = ; i <= n; i++) {
int x = i, y;
while(x > ) {
y = last[x];
if(id[y] <= m) sta[i] |= ( << (id[y] - ));
else sta[i] |= ( << m);
while(x % y == ) x /= y;
}
} LL ans = ;
f[][][] = ;
for(int i = ; i <= n; i++) {
memset(f[(i + ) & ], , sizeof(f[]));
if((sta[i] & (lm - )) != sta[i]) {
stk[++tp] = i;
memcpy(f[(i + ) & ], f[i & ], sizeof(f[i & ]));
continue;
}
for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if((s & t) || (!f[i & ][s][t])) continue;
/// f[i][s][t]
Add(f[(i + ) & ][s][t], f[i & ][s][t]);
if((sta[i] & t) == ) {
Add(f[(i + ) & ][s | sta[i]][t], f[i & ][s][t]);
}
if((sta[i] & s) == ) {
Add(f[(i + ) & ][s][t | sta[i]], f[i & ][s][t]);
}
}
}
} for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if(s & t) continue;
Add(F[s][t], f[(n + ) & ][s][t]);
}
} for(int i = ; i <= tp; i++) {
if(vis[stk[i]]) {
continue;
} memcpy(g[], F, sizeof(F));
memcpy(h[], F, sizeof(F));
int time = ;
for(int x = stk[i]; x <= n; x += stk[i], time++) {
memset(g[(time + ) & ], , sizeof(g[]));
memset(h[(time + ) & ], , sizeof(h[])); for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if(s & t) continue;
Add(g[(time + ) & ][s][t], g[time & ][s][t]);
Add(h[(time + ) & ][s][t], h[time & ][s][t]);
if((sta[time] & t) == ) {
Add(g[(time + ) & ][s | sta[time]][t], g[time & ][s][t]);
}
if((sta[time] & s) == ) {
Add(h[(time + ) & ][s][t | sta[time]], h[time & ][s][t]);
}
}
}
}
for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if(s & t) continue;
F[s][t] = -F[s][t];
Add(F[s][t], g[time & ][s][t]);
Add(F[s][t], h[time & ][s][t]);
}
}
} for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if(s & t) continue;
Add(ans, F[s][t]);
}
} printf("%lld\n", ans);
return ;
}

AC代码(容斥)

 #include <bits/stdc++.h>

 typedef long long LL;
const int N = , M = ; int n, sta[N], p[N], top, last[N], id[N], stk[N], tp;
LL f[][M][M], g[][M][M][], MO, h[][M][M][], F[M][M];
bool vis[N]; inline void Add(LL &a, const LL &b) {
a += b;
while(a >= MO) a -= MO;
while(a < ) a += MO;
return;
} inline void getp(int n) {
for(int i = ; i <= n; i++) {
if(!vis[i]) {
p[++top] = i;
id[i] = top;
last[i] = i;
}
for(int j = ; j <= top && i * p[j] <= n; j++) {
vis[i * p[j]] = ;
last[i * p[j]] = p[j];
if(i % p[j] == ) break;
}
}
return;
} int main() { //freopen("in.in", "r", stdin); scanf("%d%lld", &n, &MO);
getp(n); int m = ;
while(m < top && p[m + ] <= ) m++;
int lm = << m; for(int i = ; i <= n; i++) {
int x = i, y;
while(x > ) {
y = last[x];
if(id[y] <= m) sta[i] |= ( << (id[y] - ));
else sta[i] |= ( << m);
while(x % y == ) x /= y;
}
} LL ans = ;
f[][][] = ;
for(int i = ; i <= n; i++) {
memset(f[(i + ) & ], , sizeof(f[]));
if((sta[i] & (lm - )) != sta[i]) {
stk[++tp] = i;
memcpy(f[(i + ) & ], f[i & ], sizeof(f[i & ]));
continue;
}
for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if((s & t) || (!f[i & ][s][t])) continue;
/// f[i][s][t]
Add(f[(i + ) & ][s][t], f[i & ][s][t]);
if((sta[i] & t) == ) {
Add(f[(i + ) & ][s | sta[i]][t], f[i & ][s][t]);
}
if((sta[i] & s) == ) {
Add(f[(i + ) & ][s][t | sta[i]], f[i & ][s][t]);
}
}
}
} for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if(s & t) continue;
Add(F[s][t], f[(n + ) & ][s][t]);
}
} for(int i = ; i <= tp; i++) {
if(vis[stk[i]]) {
continue;
} //memcpy(g[1], F, sizeof(F));
//memcpy(h[1], F, sizeof(F));
for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
g[][s][t][] = F[s][t];
g[][s][t][] = ;
h[][s][t][] = F[s][t];
h[][s][t][] = ;
}
} int time = ;
for(int x = stk[i]; x <= n; x += stk[i], time++) {
memset(g[(time + ) & ], , sizeof(g[]));
memset(h[(time + ) & ], , sizeof(h[])); for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if(s & t) continue;
Add(g[(time + ) & ][s][t][], g[time & ][s][t][]);
Add(g[(time + ) & ][s][t][], g[time & ][s][t][]);
Add(h[(time + ) & ][s][t][], h[time & ][s][t][]);
Add(h[(time + ) & ][s][t][], h[time & ][s][t][]);
if((sta[time] & t) == ) {
Add(g[(time + ) & ][s | sta[time]][t][], g[time & ][s][t][]);
Add(g[(time + ) & ][s | sta[time]][t][], g[time & ][s][t][]);
}
if((sta[time] & s) == ) {
Add(h[(time + ) & ][s][t | sta[time]][], h[time & ][s][t][]);
Add(h[(time + ) & ][s][t | sta[time]][], h[time & ][s][t][]);
}
}
}
}
for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if(s & t) continue;
//F[s][t] = -F[s][t];
//F[s][t] = 0;
Add(F[s][t], g[time & ][s][t][]);
Add(F[s][t], h[time & ][s][t][]);
}
}
} for(int s = ; s < lm; s++) {
for(int t = ; t < lm; t++) {
if(s & t) continue;
Add(ans, F[s][t]);
}
} printf("%lld\n", ans);
return ;
}

AC代码(多开一维)

洛谷P2150 寿司晚宴的更多相关文章

  1. 洛谷$P2150\ [NOI2015]$寿司晚宴 $dp$

    正解:$dp$ 解题报告: 传送门$QwQ$. 遇事不决写$dp$($bushi$.讲道理这题一看就感觉除了$dp$也没啥很好的算法能做了,于是考虑$dp$呗 先看部分分?$30pts$发现质因数个数 ...

  2. UOJ #129 / BZOJ 4197 / 洛谷 P2150 - [NOI2015]寿司晚宴 (状压dp+数论+容斥)

    题面传送门 题意: 你有一个集合 \(S={2,3,\dots,n}\) 你要选择两个集合 \(A\) 和 \(B\),满足: \(A \subseteq S\),\(B \subseteq S\), ...

  3. 【Luogu】P2150寿司晚宴(状压DP)

    题目链接 反正……我是没什么想法了,全程看题解 (或者说自己想了半天错解) 因为大于根n的质数最多只会在一个数里出现一种,所以可以把数拆成两部分:小数的二进制集合和大数. 然后把大数一样的放到一起DP ...

  4. BZO4197 & 洛谷2150 & UOJ129:[NOI2015]寿司晚宴——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4197 https://www.luogu.org/problemnew/show/P2150 ht ...

  5. 【洛谷P3749】[六省联考2017]寿司餐厅(网络流)

    洛谷 题意: 给出\(n\)份寿司,现可以选取任意多次连续区间内的寿司,对于区间\([l,r]\),那么贡献为\(\sum_{i=l}^r \sum_{j=i}^rd_{i,j}\)(对于相同的\(d ...

  6. 【BZOJ-4197】寿司晚宴 状压DP

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

  7. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

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

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

  9. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

随机推荐

  1. 下拉框、下拉控件之Select2

    一.Select2的功能简介 select2插件给我们带来了更加友好的交互方式,比如查询控件展开后可通过关键字进行检索 例如: Select2也可以选择带查询控件的选择框... Select2也可以选 ...

  2. Day3-2 函数之递归

    递归 定义:一个函数在 内部调用自己,就称为递归. # 如何让10不停的除以2,直到不能除为止. n = 10 while True: n = int(n /2) print(n) if n == 0 ...

  3. BPM与OA的区别

    近年来,随着计算机技术的发展和互联网时代的到来,我们已经进入了信息时代,也称为数字化时代,在这数字化的时代里,企业的经营管理都受到了极大的挑战.从上世纪90年代起至今,企业的信息化工作开展的如火如荼, ...

  4. Android——线程通讯 Handler、Looper、Message;

    线程通讯问题 (主要用到了Handler类,Looper类和Message类以及MessageQueue) 在Android中主线程如何向子线程中发送消息的问题.让我们来想想,这其中的过程,无非就是创 ...

  5. 报错:ch.qos.logback.core.joran.spi.JoranException

    项目中使用了maven. 1.找到本地仓库,删除ch文件夹 2.对项目执行maven install 3.在更新下项目maven update

  6. Python 常用模块总结

    模块的分类: 1.内置模块(python自带的比如像os,sys等模块)    2.自定义模块,自己写的一些模块    3.第三方模块(开源模块) 模块导入: 1.import sys         ...

  7. delphi 子窗体只能最小化不能关闭的解决方案

    cnpack下载地址:http://www.cnpack.org/showdetail.php?id=726&lang=zh-cn 时候创建的子窗体不能关闭,点关闭按钮时子窗体最小化了. 出现 ...

  8. Hbase和Oracle的对比

    转自:http://www.cnblogs.com/chay1227/archive/2013/03/17/2964020.html 转自:http://blog.csdn.net/allen879/ ...

  9. Stream、FileStream、MemoryStream的区别

    1.Stream:流,在msdn的定义:提供字节序列的一般性视图,Stream提供了读写流的方法是以字节的形式从流中读取内容.而我们经常会用到从字节流中读取文本或者写入文本,微软提供了StreamRe ...

  10. html5 autoplay不起作用 Uncaught (in promise) DOMException: play() failed because the user didn't interac

    chrome://flags/#autoplay-policy