1 条题解
-
0
自动搬运
来自洛谷,原作者为

yeshubo_qwq
我是 luxu。搬运于
2025-08-24 22:42:29,当前版本为作者最后更新于2022-11-24 12:56:33,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
A
先从 个孩子中选 个孩子,给他们自己房间的钥匙,满足有 个孩子分到的是自己房间的钥匙的条件。
剩下的 个孩子要求分到的不是自己房间的钥匙,这是一个显然的错排问题。
将两部分乘起来就可以得到最后的答案。
B
要把排列 转化到 ,有两种方法:
-
不断重复操作 (转移到其下一个排列。如果当前排列已经是最后一个排列,那么下一个排列就是第一个排列)。
-
不断重复操作 (转移到其上一个排列。如果当前排列是第一个排列,那么上一个排列就是最后一个排列)。
取步骤数最小值即可。
如何快速求出步骤数?用给定全排列在所有全排列中的排名!
求排名就要用到康托展开(不会可以去看看 【模板】康托展开)。
Code
注意:本题中所有涉及到的运算都不能取模,所以第一问会爆
long long,可以用__int128或者高精度。#include <bits/stdc++.h> #define int __int128 using namespace std; void write(int x){ if (x>9) write(x/10); putchar(x%10+'0'); } namespace A{ int F[30],i; vector <int> fac; void go(){ for (F[2]=1,i=3;i<=14;i++) F[i]=(i-1)*(F[i-1]+F[i-2]); for (fac.push_back(1),i=1;i<=28;i++) fac.push_back(fac.back()*i); write(fac[28]/(fac[14]*fac[14])*F[14]); } } namespace B{ int c[20],fac[20]; int lowbit(int x){ return x & - x; } void add(int x,int v){ while (x<=17) c[x]+=v,x+=lowbit(x); } int sum(int x){ int res=0; while (x>0) res+=c[x],x-=lowbit(x); return res; } int Get(string a){ int ans=0,i; fac[0]=1; for (i=1;i<=17;i++) fac[i]=fac[i-1]*i; for (i=1;i<=17;i++) add(a[i]-'a'+1-(a[i]>'m'),1); for (i=1;i<=17;i++) ans+=sum(a[i]-'a'-(a[i]>'m'))*fac[17-i],add(a[i]-'a'+1-(a[i]>'m'),-1); return ans; } void go(){ int x=Get(" aejcldbhpiogfqnkr"); int y=Get(" ncfjboqiealhkrpgd"); write(min(y-x,fac[17]-y+x)); } } signed main(){ return (getchar()=='A'?A::go():B::go()),0; } -
- 1
信息
- ID
- 7966
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者