Two Sided Cards 题解
前言
五一网课的例题,但是网上没有详细的题解(真的连题解都找不到啊),所以来写一篇,就当攒 RP 了。题目可以在这里提交。原题是 TopCoder - 10947,但是有了账号也交不了?
题目简述
有 \(n\) 张卡片,正面和反面分别组成了 \(1 \sim n\) 的排列。现在你需要将这 \(n\) 张卡片排成一排。卡片可以以任何顺序放置,每张卡片可以显示正面或背面,排成的序列不一定是一个排列。两种方案至少存在一个位置的数字不同,则这两种方案被认为是不同的。求排成的不同的序列的方案数,答案对 \(10^9+7\) 取模。
题目分析
套路地,把卡牌当做边,正面连向反面,建图。发现形成了若干个环。环之间互不影响,所以我们只要求得一个环的方案数 \(W_i\) 即可。进而发现设环的长度为 \(L_i\),则 \(W_i\) 只跟 \(L_i\) 有关,即 \(W_i = f(L_i)\)。
考虑计算 \(f(L)\)。发现方案数和重合的数字个数有关,而每个数字要么出现一次,要么出现两次。故枚举有 \(i\) 个数字出现了两次,求出方案数,总方案数即为所有情况之积。从 \(L\) 个位置中选出 \(2i\) 个位置是重复的,方案数是 \(C_L^{2i}\),若 \(i \neq 0\),则还要乘 \(2\),因为将方案取反可以得到新的方案。接下来,不断从剩下可选的位置中选出重复的那 \(2\) 个位置,这 \(2\) 个位置没有区分。剩下的数随随便排列,方案数是 \((L-2i)!\)。这里方案数是 \(\prod \limits _ {j = 1} ^ {i} C _ {L - 2(j-1)} ^ 2\),化简得 \(\cfrac{n!}{2^i \times (L-2i)!}\)。综上:
f(L) = \sum \limits _ {i = 0} ^ {\left \lfloor \cfrac{L}{2} \right \rfloor} C_L^{2i} \times (2 - [i = 0]) \times \cfrac{L!}{2 ^ i}
\]
故总答案:
ans = \Large \prod \limits _ {i = 1} ^ {cnt} C_{n - \sum \limits _ {j = 1} ^ {i - 1} L_j}^{L_i} \times f(L_i)
\]
总体时间复杂度是 \(\Theta(n)\) 的。
代码
//#pragma GCC optimize(3)
//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx", "sse2", "sse3", "sse4", "mmx")
#include <iostream>
#include <cstdio>
#define debug(a) cerr << "Line: " << __LINE__ << " " << #a << endl
#define print(a) cerr << #a << "=" << (a) << endl
#define file(a) freopen(#a".in", "r", stdin), freopen(#a".out", "w", stdout)
#define main Main(); signed main(){ return ios::sync_with_stdio(0), cin.tie(0), Main(); } signed Main
using namespace std;
const int mod = 1000000007;
const int inv2 = 500000004;
inline int add(int a, int b){
return a + b >= mod ? a + b - mod : a + b;
}
inline int mul(int a, int b){
return 1ll * a * b % mod;
}
const int N = 100010;
int n, a[N], b[N], trans[N], f[N];
int frac[N], Inv[N], finv[N];
bool vis[N];
inline int C(int n, int m){
return mul(frac[n], mul(finv[m], finv[n - m]));
}
inline int calc(int n){
if (f[n]) return f[n];
int res = 0;
for (int i = 0, mu = 1; i <= n / 2; mu = mul(mu, inv2), ++i){
int z = C(n, i << 1);
if (i > 0) z = mul(z, 2);
z = mul(z, mul(frac[n], mu));
res = add(res, z);
}
return f[n] = res;
}
signed main(){
scanf("%d", &n);
for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
for (int i = 0; i < n; ++i) scanf("%d", &b[i]), trans[a[i] - 1] = b[i] - 1;
frac[0] = 1, finv[0] = 1;
for (int i = 1; i <= n; ++i) frac[i] = mul(frac[i - 1], i), Inv[i] = i == 1 ? 1 : mod - mul(mod / i, Inv[mod % i]), finv[i] = mul(finv[i - 1], Inv[i]);
int res = 1;
for (int i = 0, j, l = 0, r = n; i < n; ++i) if (!vis[i]){
for (j = i, l = 0; !vis[j]; ++l, vis[j] = true, j = trans[j]);
res = mul(mul(res, C(r, l)), calc(l)), r -= l;
}
printf("%d\n", res);
return 0;
}
Two Sided Cards 题解的更多相关文章
- CF949E Binary Cards 题解
题面 首先发现:一个数最多会出现1次: 然后深入推出:一个数不会既用它又用它的相反数: 这样就可以依次考虑每一位了: 如果所有的数都不含有这一位,那么就直接把所有的数除以2 如果含有,那么就减去这一位 ...
- CF908A New Year and Counting Cards 题解
Content 有 \(n\) 张卡牌,每张卡牌上只会有大小写字母和 \(0\sim 9\) 的阿拉伯数字.有这样一个描述:"如果卡牌正面写有元音字母(\(\texttt{A,E,I,O,U ...
- CF701A Cards 题解
Content 有一个长度为 \(n\) 的数组 \(a_1,a_2,a_3,...,a_n\),试在其中找到 \(\dfrac{n}{2}\) 对数,使得每个数对的元素的和都相等. 数据范围:\(2 ...
- luogu P1446 [HNOI2008]Cards
题目链接 luogu P1446 [HNOI2008]Cards 题解 题意就是求染色方案->等价类 洗牌方式构成成了一个置换群 然而,染色数限制不能用polay定理直接求解 考虑burnsid ...
- [Codeforces 864A]Fair Game
Description Petya and Vasya decided to play a game. They have n cards (n is an even number). A singl ...
- Codeforces 744C Hongcow Buys a Deck of Cards 状压dp (看题解)
Hongcow Buys a Deck of Cards 啊啊啊, 为什么我连这种垃圾dp都写不出来.. 不是应该10分钟就该秒掉的题吗.. 从dp想到暴力然后gg, 没有想到把省下的红色开成一维. ...
- CF815D Karen and Cards 官方题解翻译
看到这道题,网上没有中文版的官方题解,于是就自己翻译了一遍. 不是机器翻译,是一个字一个字纯手翻译的,如果有错误欢迎指正. 比如我们有一张卡片,三个参数分别是 a1 = 4, b1 = 2, c1 = ...
- 题解 CF546C 【Soldier and Cards】
思路 是一道水题,可以用队列+模拟来写,注意不要拿完队列中的元素! 代码 #include<iostream> #include<cstdio> #include<que ...
- CF254A Cards with Numbers 题解
Content 有 \(2n\) 个数,让你找出两两相等的 \(n\) 对数的编号,或者方案不存在. 数据范围:\(1\leqslant n\leqslant 3\times 10^5,1\leqsl ...
- bzoj 1004 Cards
1004: [HNOI2008]Cards Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有 多少种染色方案,Sun ...
随机推荐
- mysql加解密,substring substring_index函数
mysql加解密,substring substring_index函数 SELECT to_base64(AES_ENCRYPT('测试串','key12345678')) ;SELECT AES_ ...
- cuda性能优化-2.访存优化
简介 在CUDA程序中, 访存优化个人认为是最重要的优化项. 往往kernel会卡在数据传输而不是计算上, 为了最大限度利用GPU的计算能力, 我们需要根据GPU硬件架构对kernel访存进行合理的编 ...
- Nginx配置文件nginx.conf中location的匹配原则
一.空格:默认匹配.普通匹配 location / { root /home; } 二.= :精确匹配(表示匹配到 /home/resources/img/face.png 这张图片) locati ...
- linux挂载的ntfs格式硬盘无法使用回收站
linux挂载的ntfs格式硬盘无法使用回收站 解决办法: 新建回收站文件, 文件名为Trash-XXX . 比如Trash-1000 这里的1000就是你的$UID. sudo mkdir /.Tr ...
- Prometheus监控系统(二)Prometheus部署与使用
1. Prometheus安装 官网:https://prometheus.io/ 下载地址:https://prometheus.io/download/ Prometheus基于Golang编写, ...
- Linux 应用案例开发手册——基于Zynq-7010/20工业开发板
目 录 1 开发案例说明 4 2 Linux 常用开发案例 4 2.1 tl_led_flash 案例 4 2.2 tl_key_test 案例 7 2.3 tl_can_echo 案例 11 2.4 ...
- 广播变量的使用-----通过ip查询属于哪个省份
1,为什么要使用广播变量? 举一个简单的例子,我们要处理一份log文件,里面有ip地址. 20090121000132095572000|125.213.100.123|show.51.com|/sh ...
- HDFS的特点和目标,不适合场景
HDFS的特点和目标: HDFS设计优点: (一)高可靠性:Hadoop按位存储和处理数据的能力值得人们信赖; (二)高扩展性:Hadoop是在可用的计算机集簇间分配数据并完成计算任务的,这些集簇可 ...
- P9576 题解
赛时没仔细想,赛后才发现并不难. 将 \(l,r\) 与 \(l',r'\) 是否相交分开讨论. 假若不相交,那么 \(l',r' < l\) 或者 \(l',r' > r\) 并且 \( ...
- JavaSe 统计字符串中字符出现的次数
public static void main(String[] args) { // 1.字符串 String str = "*Constructs a new <tt>Has ...