• 【洛谷3214】[HNOI2011] 卡农(思维)


    点此看题面

    • 问有多少种大小为(m)、值域为([1,2^n))的无序且无重复元素的集合,满足其中所有数异或和为(0)
    • (n,mle10^6)

    巧妙的计数思想

    首先,由于集合中元素不重复,方便起见我们可以改成求有序集合数,只要最后给答案除以一个(m!)即可。

    (f_i)表示大小为(i)的集合个数。

    考虑我们随意选择前(i-1)个数(方案数为(A_{2^n-1}^{i-1})),由于异或和要为(0),那么第(i)位上的数就唯一确定了,但它并不一定满足题目中对集合的两个限制:

    1. 它不能为(0)
    2. 它不能与选中的数重复。

    容易发现,因为选中的数中不可能存在(0),是没有同时违反这两个限制的情况的,故可以分别考虑。

    如果它是(0),说明选中的这(i-1)个数异或和为(0)。这种情况的方案数正是(f_{i-1})

    如果它与某个选中的数重复(假设编号为(j)),那么除(i,j)以外的这(i-2)个数异或和也必须是(0)。这种情况方案数是(f_{i-2}),而(j)的选择有(i-1)种,对于确定的(i-2)个数(i)的取值有((2^n-1)-(i-2))种。

    因此,得到最终的计算式:

    [f_i=A_{2^n-1}^{i-1}-f_{i-1}-f_{i-2} imes (i-1) imes((2^n-1)-i+2) ]

    注意,其中的排列下标都是(2^n-1),因此可以线性预处理。

    代码:(O(logn+m))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000000
    #define X 100000007
    using namespace std;
    int n,m,A[N+5],f[N+5];
    I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
    int main()
    {
    	RI i,p;for(scanf("%d%d",&n,&m),p=QP(2,n)-1,A[0]=i=1;i<=m;++i) A[i]=1LL*A[i-1]*(p-i+1)%X;//预处理排列
    	for(f[0]=1,f[1]=0,i=2;i<=m;++i) f[i]=(0LL+A[i-1]-f[i-1]-1LL*f[i-2]*(i-1)%X*(p-i+2)%X+2*X)%X;//递推
    	RI t=1;for(i=1;i<=m;++i) t=1LL*t*i%X;return printf("%d
    ",1LL*f[m]*QP(t,X-2)%X),0;//有序化无序
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    python每日一题002
    python每日一题001
    python正则-元字符
    组合命令行生成工具pict
    接口测试工具postman安装
    python正则-group()
    树结构数据整理
    safari 调试的小问题
    a 标签 href 被浏览器拦截
    js 将浮点数的科学计数法转换成string 的 0.000000 显示
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3214.html
Copyright © 2020-2023  润新知