题目链接

题目

题目描述

​ **YZ(已被和谐)的食堂实在是太挤辣!所以Apojacsleam现在想邀请他的一些好友去校外吃一顿饭,并在某酒店包下了一桌饭。

​ 当Apojacsleam和他的同学们来到酒店之后,他才发现了这些同学们其实是N对cp,由于要保护广大单身狗的弱小心灵(FF!),所以他不想让任意一对情侣相邻。

​ 说明:

​ ·酒店的桌子是恰好有2N个位置的圆桌。

​ ·客人恰好是N对cp,也就是说,圆桌上没有空位。

​ ·桌子的每一个位置是一样的,也就是说,如果两种方案可以通过旋转得到,那么这就可以视为相等的。

​ 现在,你需要求出,将任意一对情侣不相邻的方案数。

输入描述

一行一个正整数N,表示cp的对数。

输出描述

一行一个非负整数,表示答案对1000000007取模后的值。

示例1

输入

2

输出

2

说明

两种方案:

假设1-2、3-4是两对情侣。

方案有1-3-2-4

1-4-2-3

或者你也可以认为1-3-2-4

2-3-1-4

是合法的方案。

示例2

输入

25

输出

535659175

示例3

输入

1000000

输出

270258012

说明

对于20%的数据,1<=N<=5

对于30%的数据,1<=N<=20

对于50%的数据,1<=N<=100

对于70%的数据,1<=N<=200000

对于100%的数据,1<=N<=30000000

题解

方法一

知识点:容斥原理,排列组合。

考虑容斥原理求出至少有一对cp坐在一起的方案数,最后用圆全排列减去方案数即可。

容易得到,至少有 \(i\) 对cp坐在一起的方案数:

\[2^i \binom{n}{i} (2n-i-1)!
\]

于是我们可以线性求出答案:

\[ans = \sum_{i = 0}^n (-1)^i2^i \binom{n}{i} (2n-i-1)!
\]

但这道题卡空间,注意到组合数只需要到 \(n\) 就行。

为了不需要快速幂求阶乘逆元,我们从 \(n\) 逆推,过程中处理阶乘。同时,我们可以直接使用 \(2\) 的逆元 \(\dfrac{1+P}{2}\)。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

方法二

知识点:计数dp。

因为cp是成对的,我们先取 \(n\) 对cp的其中一人安排到排列里,在考虑将剩下 \(n\) 个人往里面插入。

不妨先假设前 \(n\) 个人已经排好,考虑设 \(f_i\) 表示插入了剩下的人中前 \(i\) 个人的排列数。

考虑 \(f_i\) ,即已经插了 \(i-1\) 个人,准备插第 \(i\) 个人。转移方程有两种情况:

  1. 直接往前插入,只需要保证插入的左右不是自己的cp即可,总方案数为 \((n+i-3)f_{i-1}\) 。
  2. 插入到前面某一个人与他cp中间,因为cp相邻本身是不合法的,所以之前不可能存在这种方案,但我们可以插入到某个不合法的cp之间,这种方案就合法了,所以需要额外考虑。前面共有 \(i-1\) 个人,可以在cp的左边和右边两种情况,因此总方案数为 \(2(i-1)f_{i-2}\) 。

所以 \(f_i = (n+i-3)f_{i-1} + 2(i-1)f_{i-2}\) 。

可以考虑只保留前面两项的值,省空间。

时间复杂度 \(O(n)\)

空间复杂度 \(O(1)\)

代码

方法一

#include <bits/stdc++.h>
using namespace std;
using ll = long long; const int P = 1e9 + 7;
namespace Number_Theory {
const int N = 6e7 + 7;
int qpow(int a, ll k) {
int ans = 1;
while (k) {
if (k & 1) ans = 1LL * ans * a % P;
k >>= 1;
a = 1LL * a * a % P;
}
return ans;
}
int fact[N], invfact[N];
void init(int n) {
fact[0] = 1;
for (int i = 1;i <= n;i++) fact[i] = 1LL * i * fact[i - 1] % P;
invfact[n] = qpow(fact[n], P - 2);
for (int i = n;i >= 1;i--) invfact[i - 1] = 1LL * invfact[i] * i % P;
}
}
namespace CNM {
using namespace Number_Theory;
int C(int n, int m) {
if (n == m && m == -1) return 1; //* 隔板法特判
if (n < m || m < 0) return 0;
return 1LL * fact[n] * invfact[n - m] % P * invfact[m] % P;
}
}
/// 公式法求组合数,O(n),预处理阶乘及其逆元快速求出组合数 using namespace CNM; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
if (n == 1) {
cout << 0 << '\n';
return 0;
}
Number_Theory::init(n);
int ans = 0, pow2 = qpow(2, n), fac = fact[n - 1];
for (int i = n;i >= 0;i--) {
(ans += (i & 1 ? -1LL : 1LL) * pow2 * C(n, i) % P * fac % P) %= P;
(ans += P) %= P;
pow2 = (1LL + P) / 2 * pow2 % P;
fac = 1LL * fac * (n - i + n) % P;
}
cout << ans << '\n';
return 0;
}

方法二

#include <bits/stdc++.h>
using namespace std;
using ll = long long; const int P = 1e9 + 7; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
if (n == 1) {
cout << 0 << '\n';
return 0;
}
int f0 = 1, f1 = n - 2;// 前n个人不是cp随便排,考虑后n个人的前i个往前插的方案数
for (int i = 2;i <= n;i++) {
f0 = (1LL * f1 * (n + i - 3) % P + 1LL * f0 * (i - 1) * 2 % P) % P;
// 直接往前插有n-i-3种方案,选前i-1个人中的一个并在他和他cp中间挡着有(i-1)*2中方案
swap(f0, f1);
}
int ans = f1;
for (int i = 1;i <= n - 1;i++) ans = 1LL * ans * i % P;
cout << ans << '\n';
return 0;
}

NC19857 最后的晚餐(dinner)的更多相关文章

  1. 牛客OI周赛4-提高组 B 最后的晚餐(dinner)

    最后的晚餐(dinner) 思路: 容斥 求 ∑(-1)^i * C(n, i) * 2^i * (2n-i-1)! 这道题卡常数 #pragma GCC optimize(2) #pragma GC ...

  2. words

    conscious[英][ˈkɒnʃəs][美][ˈkɑnʃəs]consensus[英][kənˈsensəs][美][kənˈsɛnsəs] scious sensuswaterflood; de ...

  3. nowcoder OI 周赛 最后的晚餐(dinner) 解题报告

    最后的晚餐(dinner) 链接: https://www.nowcoder.com/acm/contest/219/B 来源:牛客网 题目描述 \(\tt{**YZ}\)(已被和谐)的食堂实在是太挤 ...

  4. tyvj1195 最后的晚餐

    背景 话说zhangbh001给盖子编的Windows 2012超时了(- -!),所以他不得不在自己家门口亲眼见证这个电影般的场景.虽然他不想错过这个美妙的时刻,但是他的肚子一再抗议,要求先吃完这最 ...

  5. nyoj 218 Dinner(贪心专题)

    Dinner 时间限制:100 ms  |  内存限制:65535 KB 难度:1   描述 Little A is one member of ACM team. He had just won t ...

  6. bzoj-3444 3444: 最后的晚餐(组合数学)

    题目链接: 3444: 最后的晚餐 Time Limit: 5 Sec  Memory Limit: 128 MB Description [问题背景] 高三的学长们就要离开学校,各奔东西了.某班n人 ...

  7. BZOJ3444: 最后的晚餐

    Description [问题背景] 高三的学长们就要离开学校,各奔东西了.某班n人在举行最后的离别晚餐时,饭店老板觉得十分纠结.因为有m名学生偷偷找他,要求和自己暗恋的同学坐在一起. [问题描述] ...

  8. Codeforces Educational Codeforces Round 5 B. Dinner with Emma 暴力

    B. Dinner with Emma 题目连接: http://www.codeforces.com/contest/616/problem/A Description Jack decides t ...

  9. Codeforces Gym 100342D Problem D. Dinner Problem Dp+高精度

    Problem D. Dinner ProblemTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/1003 ...

  10. nyoj 218 Dinner

    Dinner 时间限制:100 ms  |  内存限制:65535 KB 难度:1   描述 Little A is one member of ACM team. He had just won t ...

随机推荐

  1. 概率图模型 · 蒙特卡洛采样 · MCMC | 非常好的教学视频

    https://www.bilibili.com/video/BV17D4y1o7J2?p=1 非常感谢!感觉学会一点了,应该能写作业了

  2. [转帖]SQL SERVER DBCC命令详解

    https://developer.aliyun.com/article/867768   简介: SQL数据库开发 DBCC DROPCLEANBUFFERS:从缓冲池中删除所有缓存,清除缓冲区 在 ...

  3. [转帖]Google SRE 薪水,看看同样作为 SRE 的你相差多少

    https://zhuanlan.zhihu.com/p/566098252 SRE 是确保所有生产环境(Infra/Server/DBS 等)一直正常运行的人.每个网络科技公司基本都有这个部门.但是 ...

  4. 一个监控数据的思考-sockets_used

    一个监控数据的思考-sockets_used 背景 最近跟踪一个项目问题. Grafana的监控了里面有一个tcp的使用监控 CurrEstab 的数据量是: 700-2000 左右 但是同时有一个非 ...

  5. [转帖]没 K8s 用不了 Chaos Mesh?试试 Chaosd

    https://cn.pingcap.com/blog/cannot-use-chaosmesh-without-k8s-then-try-chaosd Chaosd 是什么? 相信大家对 Chaos ...

  6. [转帖]CentOS8完美升级gcc版本方法

    https://blog.whsir.com/post-6114.html 在CentOS8系统中,默认gcc版本已经是8.x.x版本,但是在一些场景中,还是需要高版本的gcc,网上一些作死的文章还在 ...

  7. [转帖]浅谈Armv8-A处理器

    https://www.elecfans.com/emb/dsp/202208291886182.html 众所周知,ARM是一家设计并授权处理器和相应IP(比如互连总线,中断处理器,图像处理器等等) ...

  8. [转帖]鹅厂微服务发现与治理巨作PolarisMesh实践-上

    文章目录 概述 定义 核心功能 组件和生态 特色亮点 解决哪些问题 官方性能数据 架构原理 资源模型 服务治理 基本原理 服务注册 服务发现 安装 部署架构 集群安装 SpringCloud应用接入 ...

  9. [转帖] Linux命令拾遗-理解系统负载

    https://www.cnblogs.com/codelogs/p/16060498.html 简介# 这是Linux命令拾遗系列的第七篇,本篇主要介绍Linux中负载的概念与问题诊断方法. 本系列 ...

  10. 一次w3wp出现crash的简单解决方案

    1. 前几天同事求助, 说一台服务器iis出现多次崩溃的现象,重启iis就可以了.  具体原因不明. 之前遇到过类似的问题  感觉最彻底的解决方案是 抓dump然后使用windbg 进行分析. 但是自 ...