zoukankan      html  css  js  c++  java
  • AGC019-E Shuffle and Swap

    给定两个长度为(nle 10^5)(01)(A, B), 满足 (1) 的数量相等

    求通过下列方式将(A)变成(B)的概率 (mod意义下)

    构造序列(a,b). 使得 (a_i = A中第i个1的位置), b同理

    (a,b)进行shuffle

    然后for i from 1 to n: swap(A[a[i]], A[b[i]])

    Analysis

    瞎推了一波

    显然, (A,B)中同为 (0) 的项没有用的, 且 答案只与 (A,B)中同为(1)的数量, 以及 (A,B)不同的数量有关

    注意到求解的问题与 原串的顺序无关, 我们调换成一种 符合自己的思维方式的序列

    A:  111111100010001000100
    B:  111111100000100010001
    a:  1111111   1   1   1 
    b:  1111111     1   1   1  
          n个         m对
    

    这是初始的 (a,b)可选 交换点 的位置

    定义一次交换为 : 选择一个未使用的交换点(a), 再选择一个未使用的交换点(b), 将他们match, 然后, 交换(A)中的对应位置

    如图

    a:  1  1  1  1     1   1   1               a:  1  0  1  1     1   1   1 
    		                                          
             ------------               =>              ------------ 
                                                                   
    b:  1  1  1  1        1   1   1            b:  1  1  1  1        0   1   1
             n                m                         n                m
    

    观察到

    (1) (a) 中的 (1) 对应着 (A)中的 (1), (B)中的(0), (b) 中的 (1) 对应着 (A)中的 (0), (B)中的(1)

    (2) (n)中的每个位置, 每个位置有两个交换点可选. (m) 中的位置, 每个位置仅有一个交换点可选

    因此, 我们不可以选择 (n) 中的 (b) 交换点 与 (m) 中的 (a) 交换点 进行匹配. 否则会使 (a) 中的该位置变成 (1), 而该位置需要是 (0), 后续又没有交换点来跟其他位置交换, 永远不能合法

    考虑被(match)位置 组成若干连通块. 因为操作是依次进行, 考虑连通块中 的 第一个操作

    (1) (n - n) : 此时, 若被匹配的是同一位置. 连通块只有一条边. 否则, 两个位置各剩余了一个交换点, 一个 (a), 一个 (b). 此时:

    这个 (a) 不能与 (m) 中的 (b) 连, 否则永远是 (0) (目前只剩一个交换点了)

    这个 (b) 不能与 (m) 中的 (a) 连, 这个是之前观察的结果

    因此, 只能继续和 (n) 内部连, 接着又有一对 (a,b), 又只能在内部连

    因此, 第一步选择了n-n连, 则只能在n内组成连通块

    注意到(A)中这些位置都是(1) , 排列顺序是可以任意的

    (2) (m-m) : 由于位置均只有一个交换点, 连通块只有一条边

    (3) (n- m) : 此时(m)中的点合法了, 但导致一个(n)中的位置变成了(0)

    接着这个 (0) 可以在 (n) 被踢皮球 传来传去

    然后最后 必须在 (m) 中的某个 (a) 结束, 即

    a:  1  1  1  1     1   1   1               a:  1  1  1  0     1   1   1 
    		                                                
                   ------               =>                    ------ 
                                                                   
    b:  1  1  1  1        1   1   1            b:  1  1  1  1        0   1   1 
             n                m                         n                m
    
    														  |
    														  v
    
    a:  0  0  0  0     1   1   1               a:  1  1  1  0     1   1   1 
    		          /                                   
         -------------                  <=                 ------ 
        /                                                        
    b:  1  0  0  0        0  1   1            b:  1  1  1  1        0   1   1 
            n                m                         n                m
    

    注意, 上图 是交换点的可用状态, 对应(A)中的(0) 从右往左一直被踢到了某个位置, 回归合法

    第一步选择了n-m, 则只能在n中转一转, 然后回到m结束

    Solution

    因此, 一个连通块内的至多一对 (m) 中的点,

    我们先用 (m!)(m)中的点 分成 (m)对, 钦定好m中的匹配方法

    然后我们先不考虑 只含 (n) 的连通块

    考虑块内的排列方案数, 对于含 (m) 连通块, 若含有 (0)(n) 中 的点, 则 方案数(=1)

    否则, 方案数 (n)个点组成一条链, (n!)

    考虑到最后要 多项式系数 把 (n)分入 不同的连通块, 多项式系数把连通块插在一起

    构造生成函数 $$F(i) = i! frac{1}{i!}frac{1}{(i+1)!}=frac{1}{(i+1)!}$$ 第一个阶乘是连通块内顺序, 第二个是把 (i) 分入不同连通块的 多项式系数分母, (i+1) 是连通块大小, 算得是连通块插在一起的分母

    那么答案为

    [m! sum_{i=1}^n F^m(i) frac{n!}{(n-i)!} frac{(n+m)!}{(n-i)!}[(n-i)!]^2=m! sum_{i=1}^n F^m(i) ~n!~(n+m)! ]

    剩下的随意排列, 随意组成连通块, 所以是阶乘的平方

  • 相关阅读:
    感触
    十道海量数据处理面试题
    jQuery横向手风琴图片滑块
    源码分享-纯CSS3实现齿轮加载动画
    Unix/Linux环境下多一点不如少一点
    参加中国系统架构师大会感悟
    Sql Server新手学习入门
    程序设计应知道的那些事儿之函数
    Windows 下如何安装配置Snort视频教程
    程序设计应知道的那些事儿
  • 原文地址:https://www.cnblogs.com/acha/p/7742493.html
Copyright © 2011-2022 走看看