传送门


数论题\(n \leq 500\)肯定是什么暴力算法……

注意到每一个数\(> \sqrt{n}\)的因子最多只有一个,这意味着\(> \sqrt{n}\)的因子之间是独立的,而只有\(\leq \sqrt{n}\)的因子之间会相互影响。而\(\leq \sqrt{n}\)的因子只有\(2,3,5,7,11,13,17,19\)总共\(8\)个,所以可以大力状压。

将\(2-n\)之间的所有数质因数分解,记录其中\(<\sqrt{n}\)的因子的出现情况,按照\(> \sqrt{n}\)的因子分类,一组一组地加入并DP。设\(dp_{i,j,k}\)表示第一个人拥有的寿司中\(<\sqrt{n}\)的因子存在情况为\(i\),第二个人拥有的寿司中\(<\sqrt{n}\)的因子存在情况为\(j\),当前计算的\(> \sqrt{n}\)的因子的存在情况为\(k\)时的方案数,转移看当前寿司分给第一个人还是第二个人。没有\(> \sqrt{n}\)因子的数先单独做一次。

总复杂度\(O(3^8n)\)

#include<iostream>
#include<cstdio>
#include<vector>
//This code is written by Itst
using namespace std;

#define int long long
const int prm[] = {2,3,5,7,11,13,17,19};
int dp[1 << 8][1 << 8][3] , N , MOD;
vector < int > Max[507];

signed main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    //freopen("out","w",stdout);
#endif
    cin >> N >> MOD;
    for(int i = 2 ; i <= N ; ++i){
        int all = 0 , x = i;
        for(int j = 7 ; j >= 0 ; --j){
            all <<= 1;
            if(x % prm[j] == 0){
                while(x % prm[j] == 0)
                    x /= prm[j];
                ++all;
            }
        }
        Max[x].push_back(all);
    }
    dp[0][0][0] = 1;
    for(auto t : Max[1])
        for(int i = (1 << 8) - 1 ; i >= 0 ; --i){
            int s = ((1 << 8) - 1) ^ i , k = s;
            while(1){
                if(!(i & t))
                    dp[i][k | t][0] = (dp[i][k | t][0] + dp[i][k][0]) % MOD;
                if(!(k & t))
                    dp[i | t][k][0] = (dp[i | t][k][0] + dp[i][k][0]) % MOD;
                if(!k) break;
                k = (k - 1) & s;
            }
        }
    for(int p = 2 ; p <= N ; ++p)
        if(!Max[p].empty()){
            for(auto t : Max[p]){
                for(int i = (1 << 8) - 1 ; i >= 0 ; --i){
                    int s = ((1 << 8) - 1) ^ i , k = s;
                    while(1){
                        if(!(i & t))
                            dp[i][k | t][1] = (dp[i][k | t][1] + dp[i][k][0] + dp[i][k][1]) % MOD;
                        if(!(k & t))
                            dp[i | t][k][2] = (dp[i | t][k][2] + dp[i][k][0] + dp[i][k][2]) % MOD;
                        if(!k) break;
                        k = (k - 1) & s;
                    }
                }
            }
            for(int i = (1 << 8) - 1 ; i >= 0 ; --i){
                int s = ((1 << 8) - 1) ^ i , k = s;
                while(1){
                    dp[i][k][0] = (dp[i][k][0] + dp[i][k][1] + dp[i][k][2]) % MOD;
                    dp[i][k][1] = dp[i][k][2] = 0;
                    if(!k) break;
                    k = (k - 1) & s;
                }
            }
        }
    int sum = 0;
    for(int i = (1 << 8) - 1 ; i >= 0 ; --i){
        int s = ((1 << 8) - 1) ^ i , k = s;
        while(1){
            sum = (sum + dp[i][k][0]) % MOD;
            if(!k) break;
            k = (k - 1) & s;
        }
    }
    cout << sum;
    return 0;
}

UOJ129 NOI2015 寿司晚宴 数论、状压DP的更多相关文章

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

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

  2. [NOI2015]寿司晚宴(状压dp)

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

  3. bzoj 4197: [Noi2015]寿司晚宴【状压dp】

    一个数内可能多个的质因数只有小于根号n的,500内这样的数只有8个,所以考虑状压 把2~n的数处理出小于根号500的质因数集压成s,以及大质数p(没有就是1),然后按p排序 根据题目要求,拥有一个质因 ...

  4. BZOJ4197 [Noi2015]寿司晚宴 【状压dp】

    题目链接 BZOJ4197 题解 两个人选的数都互质,意味着两个人选择了没有交集的质因子集合 容易想到将两个人所选的质因子集合作为状态\(dp\) \(n\)以内质数很多,但容易发现\(\sqrt{n ...

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

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

  6. 【bzoj4903/uoj300】[CTSC2017]吉夫特 数论+状压dp

    题目描述 给出一个长度为 $n$ 的序列,求所有长度大于等于2的子序列个数,满足:对于子序列中任意两个相邻的数 $a$ 和 $b$ ($a$ 在 $b$ 前面),${a\choose b}\mod 2 ...

  7. BZOJ4197 / UOJ129 [Noi2015]寿司晚宴

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

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

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

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

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

随机推荐

  1. 【Java入门提高篇】Day25 史上最详细的HashMap红黑树解析

    当当当当当当当,好久不见,最近又是换工作,又是换房子,忙的不可开交,断更了一小段时间,最重要的一篇迟迟出不来,每次都犹抱琵琶半遮面,想要把它用通俗易懂的方式进行说明,确实有一定的难度,可愁煞我也,但自 ...

  2. SpringBoot整合系列-整合Swagger2

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9959844.html SpringBoot整合Swagger2 步骤 第一步:添加必要的 ...

  3. C# 设置Excel条件格式(二)

    上一篇文章中介绍了关于设置Excel条件格式,包括基于单元格值.自定义公式等应用条件格式.应用数据条条件类型格式.删除条件格式等内容.在本篇文章中将继续介绍C# 设置条件格式的方法. 要点概述: 1. ...

  4. mysql修改连接数

    方法一:   进入MySQL安装目录 打开MySQL配置文件 my.ini 或 my.cnf查找 max_connections=100 修改为 max_connections=1000 服务里重起M ...

  5. JDK8新特性:default方法的应用实践

    背景: 最近维护一个老旧工程,遇到集团层面的数据安全改造,需要在DAO层做加解密改造.而这个老旧工程的DAO层是用的JdbcTemplate实现的,尽管template方式实现起来可自由发挥的空间很大 ...

  6. nodejs cookie与session

    cookie.session cookie:在浏览器保存一些数据,每次请求都会带过来 *不安全.有限(4K) session:保存数据,保存在服务端 *安全.无限 ------------------ ...

  7. 用JS编写一个函数,返回数组中重复出现过的元素

    用JS编写一个函数,返回数组中重复出现过的元素,见下面的代码: , , , , , , , ]; var getRepeat = function (arr) { var obj = {}; , le ...

  8. 安装屏保软件(Linux终端演示 “黑客帝国” 字母雨界面)和Linux修改管理员密码

    1.Linux修改管理员密码:打开终端:1. 重启 reboot  2.进入内核登陆系统点击e3.进入系统救援界面,定位Linux16所在行,找到ro 后删除,在此位置添加一条命令: rw init= ...

  9. Xamarin for Visual Studio下载后的文件路径

    Xamarin for Visual Studio的下载很纠结,在官网上不知道如何下载?现在找到一个办法:可以先在网上找一个低版本的之后安装,然后利用VS更新.利用VS更新这里也遇到了问题,下载成功之 ...

  10. 2-SAT速成

    本文只做总结性说明 2-SAT 2-SAT是k-SAT问题的一种,k-SAT问题在\(k>=3\)时已经被证明是NP完全问题 2-SAT问题定义比较简单 有n个布尔变量\(x_1-x_n\).给 ...