• 洛谷 P6672


    洛谷题面传送门

    题解里一堆密密麻麻的 Raney 引理……蒟蒻表示看不懂,因此决定写一篇题解提供一个像我这样的蒟蒻能理解的思路,或者说,理解方式。

    首先我们考虑什么样的牌堆顺序符合条件。显然,在摸牌任意时刻,你手中的牌允许你继续无限制摸的牌是一段区间,即存在一个位置 (p),满足你在不使用新摸出来的牌的机会下能够恰好摸到第 (p) 张牌。考虑如果我们新摸出来一张牌会产生怎样的影响,假设摸出一张 (w_i=x) 的牌,那么我们肯定会在耗完目前手中牌的机会,也就是摸完第 (p)​ 张牌后使用该牌,这样我们恰好会在摸第 (p+1,p+2,cdots,p+x) 张牌时使用这张牌摸牌的机会。因此我们考虑将原问题转化为一个区间覆盖的问题,一个点覆盖了即意味着该点能够被摸到,考虑这样的过程:

    Process:我们从左到右扫一遍,如果扫到一个 (w_i>0) 的点,就在该点后面找到距离该点最近的一段长度为 (w_i) 且区间中所有点都没有被覆盖的区间,并将这段区间所有点都设为被覆盖,那么一个牌堆符合条件当且仅当不存在某个 (le m) 的位置没有被覆盖。

    这个过程看起来有点鸡肋,我们考虑稍微变换一下,我们不一定要覆盖完整的区间,我们只需要向后找到 (w_i) 个没有覆盖的点并将它们设为被覆盖即可,不难发现这样不合法的情况,在我们新的过程中依然不合法,原来合法的情况依旧合法。

    这样还是不好直接维护,不过思路理到这一步,做过 CF838D Airplane Arrangements 的同学们应该会感到特别熟悉。没错,这道题和那道题安排飞机座位的过程是完全一致的。按照那题的套路,我们在后面补上一个 (m+1) 号点,并将这个问题放到一个环上,那么一个牌堆符合条件当且仅当第 (m+1) 个位置没有被占用。不难发现由于没有被占用的位置只有一个,因此我们考虑做这样一个变换:将牌堆沿着环按顺时针方向分别旋转 (1,2,3,cdots,m),那么由于环的对称性,对于一个合法的牌堆,在这些变换后的牌堆中,空着的位置分别是 (1,2,3,cdots,m),也就是说全部 (m+1) 个位置是等价的,因此我们只用拿总方案数除以 (m+1) 即可。那么怎么计算总方案数呢?(m!)?Nope。由于我们引入了一个 (m+1) 位置,因此我们也要相应地添上一个 (0),因此总共 ((m+1)!) 种可能,但由于我们新增的 (0) 与其他 (0) 并没有区别,也即,所有 (0) 都可以充当这个新增的 (0),对于每个合法的牌堆我们答案重复计算了 (m-n+1) 次,因此答案还需除以 (m-n+1)

    于是

    [ans=dfrac{(m+1)!}{(m-n+1)(m+1)}=dfrac{m!}{m-n+1} ]

    #include <cstdio>
    using namespace std;
    const int MOD=998244353;
    int n,m,res=1;
    int main(){
    	scanf("%d",&n);
    	for(int i=1,x;i<=n;i++) scanf("%d",&x),m+=x;
    	for(int i=1;i<=m;i++) if(i^(m-n+1)) res=1ll*res*i%MOD;
    	printf("%d
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    JavaScript——引用类型
    react+express+mongodb搭建个人博客
    JavaScript——变量及其作用域
    CSS——盒子模型
    CSS——浮动及清除浮动
    hexo博客分支教训
    使用Node.js+Express 简易开发服务端实例
    发布Nuget包命令
    当心引用类型的“坑”
    sqlcmd相关
  • 原文地址:https://www.cnblogs.com/ET2006/p/luogu-P6672.html
Copyright © 2020-2023  润新知