zoukankan      html  css  js  c++  java
  • Oier们的镜子(mirror)

    题解:

    这题真是把我坑的很惨。。

    题目看了很久才看懂。。

    然后刚开始又没看见每个只能匹配一个这种条件

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    const int N=16;
    const int N2=1<<16;
    int n,f[N][N2],g[N2],q[N],C[25][25],a[N];
    const int mo=1000000007;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      ios::sync_with_stdio(false);
      cin>>n;
      rep(i,1,n) cin>>a[i];
      sort(a+1,a+n+1);
      int lst=0;
      rep(i,1,20)
        rep(j,0,i)
          if (j==i||j==0) C[i][j]=1;
          else C[i][j]=C[i-1][j]+C[i-1][j-1];
      f[0][0]=1;
      rep(i,1,n)
      {
        if (a[i]==a[i+1]) continue;
        rep(k,0,i-lst)
        {
          rint now=0;
          rep(j,1,k)
            now^=1<<(i-j);
          rint l=(1<<lst)-1;
          rep(j,0,l)
            if (f[lst][j])
              {
                int ans1=C[i-lst][k];
                int cnt=0,ans=0;
                rep(k,0,lst-1) if ((j>>k)&1) q[++cnt]=k+1;
                int l2=(1<<cnt)-1,cnt2=0,num=0;
                rep(k1,1,l2)
                {
                  if (k1>>(cnt2+1)) cnt2++;
                  g[k1]=g[k1^(1<<cnt2)]+a[q[cnt2+1]];
                  if (g[k1]==a[i]) num++;
                }
                ans1=1ll*ans1*f[lst][j]%mo;
                ans=1ll*(num+k)%mo;
                rep(p,1,i-lst-k) ans1=1ll*ans1*ans%mo;
                f[i][j^now]=ans1;
              }
        }
        lst=i;
      }
      int ans=0;
      rep(i,0,(1<<n)-1)
        ans=(ans+f[n][i])%mo;
      cout<<ans<<endl;
      return 0;
    }

    然后又思考怎么处理相同元素思考了比较久

    我自己写了一种特判相同元素的方法。。。非常复杂。。。(还是看错题目的),之后就没改了

    大致就是枚举这些元素里哪些是镜子,哪些是由东西组合的,然后再乘组合数再乱搞。。

    首先这道题目状压dp是比较显然的

    排序也是比较显然的

    然后唯一的问题在于相同元素怎么办

    有一个非常巧妙的办法就是

    当f[i][j]通过相同元素转移,那么要把这个东西乘二

    为什么呢,我们可以这么理解,如果你要把右边的那个东西当镜子,左边的当元素

    那么和左边当镜子,右边当元素方案数是等价的

    因为由于这道题的特性每个元素只能对应一个,所以对于这两个元素,有关联的只有互相

    // luogu-judger-enable-o2
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    #define lowbit(x) (x&(-x))
    const int N=16;
    const int N2=1<<15;
    int n,a[N],b[N2],sum[N2],f[N][N2];
    const int mo=1e9+7;
    void js(int &x,int y)
    {
      x+=y;
      x%=mo;
    }
    int main()
    {
      ios::sync_with_stdio(false);
      cin>>n;
      rep(i,1,n) cin>>a[i];
      sort(a+1,a+n+1);
      rep(i,1,n) b[1<<(i-1)]=a[i];
      int l=(1<<n)-1;
      f[0][0]=1;
      rep(i,1,l) sum[i]=sum[i-lowbit(i)]+b[lowbit(i)];
      rep(i,1,n)
      {
        rep(j,0,l)
          if (f[i-1][j])
          {
            js(f[i][j|(1<<(i-1))],f[i-1][j]);
            for(rint k=j;k;k=(k-1)&j)
              if (sum[k]==a[i])
              {
                js(f[i][j^k],f[i-1][j]);
                if (!(k-lowbit(k))) js(f[i][j^k],f[i-1][j]);
              }
          }
      }
      int ans=0;
      rep(i,0,l) js(ans,f[n][i]);
      cout<<ans<<endl;
      return 0; 
    }

     同学给了我一种新的方法。。

    我们可以比较暴力的做

    每次枚举一个数,然后枚举子集可以用哪些东西构成

    记录一下用了几组,最后除掉就行了

    7*3^n并不能过

    然后可以用fwt优化

  • 相关阅读:
    java中为什么notify()可能会导致死锁,而notifyAll()则不会
    java中wait()和sleep()的区别;notify()和notifyall()区别
    你不知道的Golang盲点汇总【持续更新】
    rsync性能终极优化【Optimize rsync performance】
    基于cephfs搭建高可用分布式存储并mount到本地
    检测代码潜在bug和质量之SonarQube
    玩透二叉树(Binary-Tree)及前序(先序)、中序、后序【递归和非递归】遍历
    好用到哭!8个技巧让Vim菜鸟变专家
    Golang fmt Printf 格式化参数手册/详解/说明
    淘宝滑动验证码研究
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9551680.html
Copyright © 2011-2022 走看看