Luogu 2150 [NOI 2015] 寿司晚宴

2023-05-16

          • 传送门
          • 思路
          • 对于 30%30%30\% 的数据
          • 对于 100%100%100\% 的数据
          • 参考代码

传送门
思路

  唉,我太弱了,什么都不会,完全做不来,连暴力都打不来。主要好像是因为我从来没有做过以质因子为状态的状压 DP?唉,我太弱啦!

对于 30% 30 % 的数据

  互质的本质是不存在相同的质因子。设 fi,S1,S2 f i , S 1 , S 2 表示考虑前 i i 个数,第一个人选择的质因子集合为 s1,第二个人选择的为 s2 s 2 。状态转移方程为(只能使用刷表法):

fi+1,S1,S2 += fi,S1,S2 f i + 1 , S 1 , S 2  +=  f i , S 1 , S 2
fi+1,S1maski+1,S2 += fi,S1,S2(S2maski+1=) f i + 1 , S 1 ∪ m a s k i + 1 , S 2  +=  f i , S 1 , S 2 ( S 2 ∩ m a s k i + 1 = ∅ )
fi+1,S1,S2maski+1 += fi,S1,S2(S1maski+1=) f i + 1 , S 1 , S 2 ∪ m a s k i + 1  +=  f i , S 1 , S 2 ( S 1 ∩ m a s k i + 1 = ∅ )

  时间复杂度为 O(n×220) O ( n × 2 20 ) ,显然可以通过,但是需要使用滚动数组。发现其实可以倒序枚举,这样只需要开一维数组就可以了,类似于背包。(神仙们太强啦!一眼就可以一维数组滚动!我看了半天才看出来为什么不会出错(写在代码里的)。唉,我太弱啦!)

对于 100% 100 % 的数据

  这种题,一般都会想到 。仔细想一下,发现一个数最多只可能有一个大于 n n 的质因子(有两个就大于 n n 了),所以我们从这里下手。然后我就真的不会了。

  我们把数按照其大于 n 的质因子分类,特别地,如果一个数不存在大于 n n 的质因子,我们令其大质因子为 1 1 。我们将大质因子相同的数视为同一类,然后一类一类处理。显然,对于两类不同的数,只要满足了小质因子的交集为空集并且对于任意一类数都只有至多一个人去取。特别地,大质因子为 1 的那一类允许两个人同时取。这样,不同类的数就相互独立了

  我们考虑一类一类地进行动态规划。设 fi,j,S1,S2 f i , j , S 1 , S 2 表示考虑了大质因子小于 i i 的所有数以及大质因子等于 i 的前 j j 个数时,A选的小质因子集合为 S1,B 为 S2 S 2 时的方案数(一群神仙,带有滚动数组的状态从来不需要补充完整,直接设,真的是太强啦!我只有把整个状态写出来才看得懂,我真是太弱啦!)。显然对于 i=1 i = 1 的情况做法与前面部分相同。

  我们考虑 i>1 i > 1 的情况。设 gi,j,S1,S2,0/1 g i , j , S 1 , S 2 , 0 / 1 表示考虑了大质因子小于 i i 的所有数以及大质因子等于 i 的前 j j 个数,且大质因子等于 i 的数由 A/B 来取(可以选择不取),第一个人选的小质因子集合为 S1 S 1 ,第二个人为 S2 S 2 时的方案数。前面已经说了,对于大质因子大于 1 1 的数最多只能有一个人去取,所以这么设状态是明确的。

  显然边界条件为 gi,0,S1,S2,0/1=fi1,all,S1,S2(都还没有开始选,当然啦)。 g g 的转移和之前的 f 很相似,只不过只能有其中一个人进行选择。我们同样使用刷表法:

gi,j+1,S1,S2,0 += gi,j,S1,S2,0 g i , j + 1 , S 1 , S 2 , 0  +=  g i , j , S 1 , S 2 , 0
gi,j+1,S1maski,j+1,S2,0 += gi,j,S1,S2,0(S2maski,j+1=) g i , j + 1 , S 1 ∪ m a s k i , j + 1 , S 2 , 0  +=  g i , j , S 1 , S 2 , 0 ( S 2 ∩ m a s k i , j + 1 = ∅ )
gi,j+1,S1,S2,1 += gi,j,S1,S2,1 g i , j + 1 , S 1 , S 2 , 1  +=  g i , j , S 1 , S 2 , 1
gi,j+1,S1,S2maski,j+1,1 += gi,j,S1,S2,1(S1maski,j+1=) g i , j + 1 , S 1 , S 2 ∪ m a s k i , j + 1 , 1  +=  g i , j , S 1 , S 2 , 1 ( S 1 ∩ m a s k i , j + 1 = ∅ )

  我们又有:

fi,all,S1,S2=gi,all,S1,S2,0+gi,all,S1,S2,1fi,0,S1,S2 f i , a l l , S 1 , S 2 = g i , a l l , S 1 , S 2 , 0 + g i , a l l , S 1 , S 2 , 1 − f i , 0 , S 1 , S 2

  两个 g g 相加很显然:要么 A 来,要么 B B 来,满足加法原理。减去右式的原因是 A 和 B 都可以不选以 i 为大质因子的数,所以这样这种情况就算了两次。显然这种情况的方案数就是 fi,0,S1,S2 f i , 0 , S 1 , S 2 ,所以减去它就可以了。

  然后我们进行滚动数组优化,发现跟前面一样可以不保存 i i j,只需要倒着枚举集合就可以了。这样就有了状态转移方程的形式就和绝大部分题解一样了(唉,神仙的题解我根本看不懂,我太弱啦!)。

参考代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <cctype>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <functional>
#define loop register int 
typedef long long LL;
typedef unsigned long long ULL;
using std::cin;
using std::cout;
using std::endl;
typedef LL INT_PUT;
INT_PUT readIn()
{
    INT_PUT a = 0; bool positive = true;
    char ch = getchar();
    while (!(ch == '-' || std::isdigit(ch))) ch = getchar();
    if (ch == '-') { positive = false; ch = getchar(); }
    while (std::isdigit(ch)) { a = a * 10 - (ch - '0'); ch = getchar(); }
    return positive ? -a : a;
}
void printOut(INT_PUT x)
{
    char buffer[20]; int length = 0;
    if (x < 0) putchar('-'); else x = -x;
    do buffer[length++] = -(x % 10) + '0'; while (x /= 10);
    do putchar(buffer[--length]); while (length);
}

const int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
LL mod;
int n;

#define RunInstance(x) delete new x
struct brute
{
    int mask[35];
    LL f[1 << 10][1 << 10];

    brute() : mask(), f()
    {
        for (int i = 2; i <= n; i++)
            for (int j = 0; j < 10; j++)
                if (i % prime[j] == 0)
                    mask[i] |= 1 << j;

        int U = 1 << 10;
        f[0][0] = 1;
        for (loop i = 2; i <= n; i++)
        {
            loop m = mask[i];
            for (loop S1 = U - 1; ~S1; S1--)
                for (loop S2 = U - 1; ~S2; S2--) if (f[S1][S2])
                {
                    if (!(S2 & m))
                        (f[S1 | m][S2] += f[S1][S2]) %= mod;
                    if (!(S1 & m))
                        (f[S1][S2 | m] += f[S1][S2]) %= mod;
                    // 唯一会出错的情况是: (!(S2 & mask[i + 1])) && (!(S1 & mask[i + 1])) && ((S1 | mask[i + 1]) == S1),
                    // 即 f[S1][S2] 在自增后再去更新其它的
                    // 显然第二个条件和第三个条件矛盾,因此不会出错
                }
        }

        LL ans = 0;
        for (loop S1 = 0; S1 < U; S1++)
            for (loop S2 = 0; S2 < U; S2++)
                (ans += f[S1][S2]) %= mod;
        printOut(ans);
    }
};
struct work
{
    struct Number
    {
        int num;
        int mask;
        int big;
        Number() {}
        Number(int num, int mask, int big) : num(num), mask(mask), big(big) {}
        bool operator<(const Number& b) const { return big < b.big; }
    };
    std::vector<Number> number[505];

    LL f[1 << 8][1 << 8];
    LL g[2][1 << 8][1 << 8];

    work() : f()
    {
        for (int i = 2; i <= n; i++)
        {
            int t = i;
            int mask = 0;
            for (int j = 0; j < 8; j++)
            {
                if (t % prime[j]) continue;
                mask |= 1 << j;
                while (!(t % prime[j]))
                    t /= prime[j];
            }
            number[t].push_back(Number(i, mask, t));
        }

        int U = 1 << 8;
        f[0][0] = 1;
        for (int i = 0; i < number[1].size(); i++)
        {
            loop m = number[1][i].mask;
            for (loop S1 = U - 1; ~S1; S1--)
                for (loop S2 = U - 1; ~S2; S2--) if (f[S1][S2])
                {
                    if (!(S2 & m))
                        (f[S1 | m][S2] += f[S1][S2]) %= mod;
                    if (!(S1 & m))
                        (f[S1][S2 | m] += f[S1][S2]) %= mod;
                }
        }

        for (int i = 2; i <= n; i++) if (number[i].size())
        {
            memcpy(g[0], f, sizeof(g[0]));
            memcpy(g[1], g, sizeof(g[1]));
            for (int j = 0; j < number[i].size(); j++)
            {
                loop m = number[i][j].mask;
                for (loop S1 = U - 1; ~S1; S1--)
                    for (loop S2 = U - 1; ~S2; S2--) if (g[0][S1][S2])
                    {
                        if (!(S2 & m))
                            (g[0][S1 | m][S2] += g[0][S1][S2]) %= mod;
                        if (!(S1 & m))
                            (g[1][S1][S2 | m] += g[1][S1][S2]) %= mod;
                    }
            }
            for (loop S1 = U - 1; ~S1; S1--)
                for (loop S2 = U - 1; ~S2; S2--)
                    f[S1][S2] = ((g[0][S1][S2] + g[1][S1][S2] - f[S1][S2]) % mod + mod) % mod;
        }

        LL ans = 0;
        for (loop S1 = 0; S1 < U; S1++)
            for (loop S2 = 0; S2 < U; S2++)
                (ans += f[S1][S2]) %= mod;
        printOut(ans);
    }
};

void run()
{
    n = readIn();
    mod = readIn();
    if (n <= 30)
        RunInstance(brute);
    else
        RunInstance(work);
}

int main()
{
    run();
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Luogu 2150 [NOI 2015] 寿司晚宴 的相关文章

  • GetExitCodeProcess 所需运行时间

    GetExitCodeProcess 在 Windows 中用于获取进程的返回代码 这个看上去只有一个读操作的函数运行速度如何呢 xff1f 直觉上不会很快 xff0c 因为它肯定涉及操作系统进程表的操作 下面做了一个实验 代码 xff1a
  • C++ 继承时返回值或参数的类型是父类的行为

    见以下代码的 base t amp operator 61 const base t amp another 还没有搞清楚 span class token macro property span class token directive
  • LaTeX 007:texify 调用 zhmakeindex

    如文档所述 xff0c 在系统增加一个值为 zhmakeindex 路径的环境变量 MAKEINDEX 即可
  • 转载:LaTeX 定义参数变长的命令

    本文作者 xff1a Liam Huang 本文链接 xff1a https liam page 2017 07 30 define a new command with different amount of parameters in
  • 一个简单的 Lex 词法分析程序示例

    作为一个学习 Lex 词法分析程序的例子 xff0c 下面的 lex 程序将会生成一个分析 LaTeX 中命令的词法分析器 下面的程序包含了很多 lex 语言的语法 xff0c 正则表达式除外 正则表达式的用法网上比较多 xff0c 这里不
  • mysql数据库conf配置详解

    mysqld port 61 6033 skip grant tables datadir 61 usr tools mysql data socket 61 usr tools mysql mysql sock user 61 mysql
  • LaTeX 008:比较方便的键入下划线的方式

    在 LaTeX 中 xff0c 我们有时会需要输入下划线 直接键入 是不行的 xff0c 会出现的编译错误 xff0c 正如网友所述 xff0c LaTeX 为了简化对编译错误的处理禁止在文本模式 xff08 text mode xff09
  • LaTeX 009:自定义带有 * 号的命令

    LaTeX 中 xff0c 我们经常见到 section 和 section xff0c 分别表示有编号的 section 和没有编号的 section 我们也想自己定义带有 号的命令 xff0c 但写下面的代码时却报错了 xff1a ne
  • 2022 New Year‘s Resolution

    Some Might Say 2022 New Year 39 s Resolution Some might say we are on the edge of the new era Always are they saying thi
  • C++ 多线程编程导论(中)

    受篇幅限制 xff0c 上半部分不再更新 xff0c 填坑的新内容都放在此文章中 文章目录 参考资料线程安全 xff08 续 xff09 互斥访问 互斥体 xff08 mutex xff09 和锁 xff08 lock xff09 什么是互
  • C++ 使用模板序列化/反序列化固定键值对

    仅是一个原型 xff0c 留作记录 我感觉可以写出非常逆天的代码 span class token macro property span class token directive hash span span class token d
  • 编译原理习题两则(龙书,写出语言的正则定义)

    3 3 5 3 注释 xff0c 即 和 之间的串 xff0c 且串中没有不在双引号 xff08 34 xff09 中的 注 xff1a 假设双引号是匹配的 思路 xff1a 从空串开始写 xff0c 写出整体框架后 xff0c 通过分类讨
  • 2023 New Year‘s Resolution

    This Is Game 2023 New Year 39 s Resolution My 2022 ended with a day of game I am convinced that I am not to blame becaus
  • 补录:2018 和 2019 New Year‘s Resolution

    前言 xff1a 吉光片羽 xff0c 以飨读者 2018 New Year 39 s Resolution One year and a half ago I felt that life in 2020 would be quite d
  • 原博文地址

    由于账号问题 xff0c 现更改为这个账号 xff0c 以下为原博文地址 使用WH MOUSE LL钩子来判断按键是否是mouse event模拟的 http blog csdn net qq 26140973 article detail
  • [NOI 2003] 文本编辑器 Splay 维护序列 / 块状链表

    传送门 xff08 JZOJ xff09 xff08 第一道全国决赛题 xff09 解法 1 xff1a 使用 Splay 维护 不管怎么说 xff0c 总和刚刚学过的迎合上了 这道题可以直接上 Splay 维护线性序列 xff0c 光标位
  • 一次macOS的升级填坑(macOS Catalina - macOS Monterey)

    目录 小序一 升级前操作二 升级中三 问题填坑1 像我一样长时间卡在一个进度条怎么办2 在更新途中重启过电脑 xff08 完整流程填坑 xff09 3 安装之后不能开机 xff0c 如何紧急拷贝资料4 安装不成功 xff0c 如何重新安装系
  • CF 713C Sonya and Problem Wihtout a Legend

    文章目录 传送门题目大意正解通过维护关键点来维护信息参考代码 传送门 题目大意 给定一个长度为 n n 3000
  • Luogu 3642 [APIO 2016] 烟火表演

    传送门引例 xff08 上一道题 xff09 凸函数一开始的思路正解参考代码总结 传送门 引例 xff08 上一道题 xff09 凸函数 回忆我们上一道题是怎么做的 我们维护的东西的实质是一个 xff08 下 xff09 凸函数 由于我们的
  • Luogu 3631 [APIO 2011] 方格染色

    传送门思路参考代码细节 传送门 思路 很不错的一道题 xff0c 用到的东西不深 xff0c 但是要想到确实需要一定思维 一开始我想的是动态规划 xff0c 发现如果要设状态需要知道一个格子左边 xff0c 上边和左上边三个格子的状态 然后

随机推荐

  • Luogu 3632 [APIO 2011] 寻路

    传送门正解参考代码 传送门 正解 暴力连边跑最短路就好了 xff0c 只不过代码太长太难写啦 xff01 参考代码 span class hljs preprocessor include lt cstdio gt span span cl
  • Luogu 3634 [APIO 2012] 守卫

    传送门思路正解参考代码 传送门 思路 感觉自己越来越笨了 首先 xff0c 很明显这道题需要把没有看到忍者的区间给删去 xff0c 可以用前缀和 O n O n 处理 xff0c 然后对没有删去的地方重新标号 重新标号时 xff0c 需要对
  • Luogu 1552 [APIO 2012] 派遣

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题读错了两次 xff0c 一开始读成了一个一般的背包 xff0c 然后读成了一个价值和花费相同的背包 xff0c 最后才发现原来是一个价值为 1
  • 贪玩 CF 之旅

    文章目录 CF 7D Palindrome Degree http codeforces com problemset problem 7 D 题解 CF 713C Sonya and Problem Wihtout a Legend ht
  • Luogu 3638 [APIO 2013] 机器人

    传送门思路正解参考代码关于 SPFA 传送门 思路 n n 这么小 会不会是搜索题 稍有经验的我直接否定了这个结论 仔细读题并分析样例 发现原来一个位置可以有多个机器人 且机器人行走的时候无视其它机器人 那这个就是一张图啊 可以将这张图预处
  • Luogu 3647 [APIO 2014] 连珠线

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 又看错题了 题目中说一个新的珠子和一个已经添加的珠子连接起来 xff0c 我没有看到 xff0c 然后就凉了 立个 flag xff1a 已经连续看错五题了 xff0c
  • 【转】mingw64的安装方法

    转自 xff1a http write blog csdn net postlist mingw64的安装方法 1 下载ming w64 http sourceforge net projects mingw w64 files or x8
  • Luogu 3645 [APIO 2015] 雅加达的摩天楼

    传送门思路正解参考代码Update 传送门 思路 唉 xff0c 我太弱了 xff0c 我都看出来要分块了 xff0c 就是做不来 不过终于把题读对了 先来看子任务三怎么做 显然可以有一个 O m 2 O m 2
  • Luogu 3644 [APIO 2015] 八邻旁之桥

    传送门思路当 k 61 2 时参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题也做不来 很明显这道题先要把不过河的人排除了 xff0c 剩下的都是要过河的 当 k 61 1 k 61 1 时 xff0
  • Luogu 3646 [APIO 2015] 巴厘岛的雕塑

    传送门总结 APIO 2015思路参考代码总结 传送门 总结 APIO 2015 争取今天做完一套 QAQ T1 我最多之能想到从高位向低位做 xff0c 然后就完全不会了 xff1b T2 我想到了分情况讨论 xff0c 但是没有建图成功
  • UOJ 2016 [APIO 2016] Gap

    传送门思路参考代码交互题 交互题大致形式Windows 平台下 xff08 Dev C 43 43 xff09 Ubuntu 平台下 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 题也做不来 这道题简直就是利用
  • CF 940F Machine Learning

    传送门题目大意思路参考代码Remarks 传送门 题目大意 给你一个数组 a 1 n n 10 5 a 1 n
  • CF 976D Degree Set

    传送门题目大意思路参考代码总结 传送门 题目大意 给你一个长度为 n n 的正整数序列 d 1 d 2 d n d1 d2 dn xff08 d 1 lt d 2 lt lt d n
  • Luogu 3778 [APIO 2017] 商旅

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 看到这道题就想到了二分答案找负环 xff0c 但是怎么做呢 xff1f 完全不会 唉 xff0c 我太弱啦 xff01 先注意题目中说可以重复经过点和边 x
  • CF 963E Circles of Waiting

    传送门题目大意思路参考代码 传送门 题目大意 在平面直角坐标系上 xff0c 有一个神奇的点 xff0c 一开始在 0 0 0 0 每秒钟这个点都会随机移动 xff1a 如果它在 x y
  • CF 976F Minimal k-covering

    传送门题目大意 输入格式输出格式 思路参考代码 传送门 题目大意 给你一张二分图 G 61 U V E G 61 U V
  • CF 963A Alternating Sum

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 好不容易做得来一道题 xff0c 还是 A 题 xff08 所以不要瞧不起 A 题 xff09 xff0c 结果还写错了 xff08 不知道为什
  • iOS中瀑布流布局详解

    前段时间在逛淘宝的时候发现淘宝的商品界面的布局是瀑布流 我记得明明之前不是瀑布流的 x1f611 刚好手上活忙完了 xff0c 写了一个瀑布流的布局 xff0c 简单的封装了下 xff0c 以便日后使用 x1f60f 其实说到底瀑布流也就是
  • Luogu 2146 [NOI 2015] 软件包管理器

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 好不容易遇到一道傻逼题 xff0c 又出了个傻逼错误 xff0c 爆得只剩 30 30 分了 唉 xff0c 我太弱啦 xff01 显然 xff
  • Luogu 2150 [NOI 2015] 寿司晚宴

    传送门思路对于 30 30 30 的数据对于 100 100 100 的数据参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 完全做不来 xff0c 连暴力都打不来 主要好像是因为我从来没有做过以质因子为