zoukankan      html  css  js  c++  java
  • bzoj 2339: [HNOI2011]卡农

    Description

    题面

    Solution

    比较难想....
    我们先考虑去掉无序的这个条件,改为有序,最后除 (m!) 即可
    (f[i]) 表示前(i)个合法集合的方案数
    明确一点:
    如果前(i-1)个集合已经确定,并且前(i)个是合法的,那么第(i)就是确定的,所以是一一对应的关系,如果不考虑重复和空集的情况,那么总方案数就是 (A_{2^{n}-1}^{i-1})
    考虑去掉不合法的:
    1.当前集合为空集,方案数为 (f[i-1])
    2.有两个集合相同,那么去掉这两个集合的方案数是 (f[i-2]),由于重复的那个位置可以取 (i-1) 个位置,且只与这个集合重复,而不与其他集合重复,所以两个集合可以取 (2^{n}-1-(i-2))
    然后直接递推即可,(log)求逆的话,复杂度就是 (O(n*logn))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e6+5,mod=1e8+7;
    int qm(int x,int k){
      int sum=1;
      while(k){
        if(k&1)sum=1ll*sum*x%mod;
        x=1ll*x*x%mod;k>>=1;
      }
      return sum;
    }
    int f[N],Fac[N];
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      int n,m,x,t,jc=1;
      cin>>n>>m;
      t=qm(2,n);Fac[1]=x=(t-1+mod)%mod;
      Fac[0]=1;
      for(int i=1;i<=m;i++)
        jc=1ll*i*jc%mod,Fac[i]=1ll*Fac[i-1]*x%mod,x=(x-1+mod)%mod;
      f[0]=1;f[1]=0;
      for(int i=2;i<=m;i++){
        f[i]=Fac[i-1];
        f[i]=(f[i]-f[i-1]-1ll*f[i-2]*(i-1)%mod*(t-1-(i-2)))%mod;
      }
      if(f[m]<0)f[m]+=mod;
      f[m]=1ll*f[m]*qm(jc,mod-2)%mod;
      cout<<f[m]<<endl;
      return 0;
    }
    
    
  • 相关阅读:
    HDU 1207 汉诺塔II (递推)
    HDU 3172 Virtual Friends (map+并查集)
    HDU 1272 小希的迷宫(并查集)
    hihoCoder #1037 : 数字三角形 (动态规划)
    51Nod 1256 乘法逆元
    AtCoder Regular Contest 077 D
    AtCoder Regular Contest 077 C
    AtCoder Beginner Contest 066 B
    AtCoder Beginner Contest 045 C
    AtCoder Beginner Contest 045 B
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8445693.html
Copyright © 2011-2022 走看看