zoukankan      html  css  js  c++  java
  • HZOJ 巨神兵

    60pts:

    每个DAG的拓扑序是唯一的,所以考虑将DAG分层。f[i][j]记录当前选择的节点状态是i,最后一层的节点状态为j(dep取最大)。

    初始状态:$f[i][i]=1;iin [1,1<<n)$。那么我们第一层枚举当前状态i,第二层枚举[1,1<<n)。那么令s=i&j,t=j&(~i),s即为i的一个子集,所以令s为当前的最后一层,t为i

    的补集的一个子集,令t为转移后的最后一层,要求s到t中每个点都有边。枚举t中每个点,设ch1为集合$i-s$当前点的边数,ch2为s集合到当前点的边数,转移方程:$f[i$|$t][t]+=f[i][s]*prod 2^{ch1}*prod (2^{ch2}-1)$;

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<bitset>
     5 #include<vector>
     6 #define LL long long
     7 using namespace std;
     8 const int mod=1e9+7;
     9 struct edge
    10 {    
    11     int u,v,nxt;
    12     #define u(x) ed[x].u
    13     #define v(x) ed[x].v
    14     #define n(x) ed[x].nxt
    15 }ed[10000];
    16 int first[21],num_e;
    17 #define f(x) first[x]
    18 int n,m,ru[21];
    19 LL f[1<<11][1<<11];
    20 vector<int> fr[21];
    21 bool pd(int s,int t)
    22 {    
    23     bool ok=1;
    24     for(int i=1;i<=n;i++)
    25     if((1<<i-1)&t)
    26     {
    27         bool pd2=0;
    28         for(int j=0;j<fr[i].size();j++)
    29         if((1<<fr[i][j]-1)&s)pd2=1;
    30         ok&=pd2;
    31     }
    32     return ok;
    33 }
    34 LL find(int s,int po)
    35 {
    36     int res=0;
    37     for(int i=0;i<fr[po].size();i++)
    38     if((1<<fr[po][i]-1)&s)res++;
    39     return res;
    40 }
    41 LL poww(LL a,int b);
    42 inline void add(int u,int v);
    43 signed main()
    44 {    
    45     cin>>n>>m;int tu,tv;
    46     for(int i=1;i<=m;i++)cin>>tu>>tv,add(tu,tv),ru[tv]++,fr[tv].push_back(tu);
    47 
    48     for(int i=1;i<(1<<n);i++)f[i][i]=1;
    49     for(int i=1;i<(1<<n);i++)    
    50     {
    51         for(int j=1;j<(1<<n);j++)
    52         {
    53             int s=i&j,t=j&(~i);
    54             bitset<3>t1(i),t2(s),t3(t);
    55 //            cout<<t1<<" "<<t2<<" "<<(t1|t3)<<" "<<t3<<endl;
    56             if(s&&t&&pd(s,t))
    57             {
    58                 int ch1=1,ch2=1;
    59                 for(int k=1;k<=n;k++)
    60                 if((1<<k-1)&t)
    61                 {
    62                     int cnt1=find(i&(~s),k),cnt2=find(s,k);
    63                     ch1=ch1*poww(2,cnt1)%mod;ch2=ch2*(poww(2,cnt2)-1)%mod;
    64                 }
    65                 f[i|t][t]=((f[i|t][t]+f[i][s]*ch1*ch2)%mod)%mod;
    66             }
    67 //            cout<<f[i][s]<<" -> "<<f[i|t][t]<<endl;
    68         }
    69     }
    70     LL ans=0;
    71 //    for(int i=1;i<(1<<n);i++)    
    72         for(int j=1;j<(1<<n);j++)
    73             ans=(ans+f[(1<<n)-1][j])%mod;
    74     printf("%lld
    ",ans);
    75 }
    76 inline void add(int u,int v)
    77 {
    78     ++num_e;
    79     u(num_e)=u;
    80     v(num_e)=v;
    81     n(num_e)=f(u);
    82     f(u)=num_e;
    83 }
    84 LL poww(LL a,int b)
    85 {    
    86     LL ans=1;
    87     while(b)
    88     {    
    89         if(b&1)ans=ans*a%mod;
    90         a=a*a%mod;b=b>>1;
    91     }
    92     return ans;
    93 }
    View Code

    100pts:

    考虑将第二维去掉,f[i]表示当前集合为i时的方案数,那么$f[i]=sum f[i][j]$,如果不记录最后一层的话,每一个j都会被计算进去多次,所以容斥一下就可以了(稍不明白)。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<bitset>
     5 #include<vector>
     6 #define re register
     7 #define co const 
     8 #define rec re co
     9 #define LL long long
    10 using namespace std;
    11 const int mod=1e9+7;
    12 struct edge
    13 {    
    14     int u,v,nxt;
    15     #define u(x) ed[x].u
    16     #define v(x) ed[x].v
    17     #define n(x) ed[x].nxt
    18 }ed[10000];
    19 int first[21],num_e;
    20 #define f(x) first[x]
    21 int n,m,ru[21];
    22 LL f[1<<21],g[1<<18];
    23 int tem[1<<21][21];
    24 vector<int> fr[21];
    25 bool pd(int s,int t)
    26 {    
    27     bool ok=1;
    28     for(int i=1;i<=n;i++)
    29     if((1<<i-1)&t)
    30     {
    31         bool pd2=0;
    32         for(int j=0;j<fr[i].size();j++)
    33         if((1<<fr[i][j]-1)&s)pd2=1;
    34         ok&=pd2;
    35     }
    36     return ok;
    37 }
    38 LL find(rec int s,rec int po)
    39 {
    40     int res=0;
    41     for(int i=0;i<fr[po].size();i++)
    42     if((1<<fr[po][i]-1)&s)res++;
    43     return res;
    44 }
    45 int pw[10010];
    46 int siz[1<<21];
    47 LL poww(LL a,int b);
    48 inline void add(rec int u,rec int v);
    49 signed main()
    50 {    
    51 //    freopen("obelisk9.in","r",stdin);
    52     
    53     cin>>n>>m;int tu,tv;
    54     for(re int i=1;i<=m;i++)scanf("%d%d",&tu,&tv),add(tu,tv),ru[tv]++,fr[tv].push_back(tu);
    55 
    56     for(re int i=1;i<(1<<n);i++){bitset<21>t(i);siz[i]=t.count();}
    57     for(re int i=0;i<(1<<n);i++)for(re int j=1;j<=n;j++)tem[i][j]=find(i,j);
    58     f[0]=1;
    59     pw[0]=1;for(int i=1;i<=10000;i++)pw[i]=pw[i-1]*2%mod;
    60     for(int i=1;i<=n;i++)g[1<<i-1]=i;
    61     int tttttt=(1<<n);
    62     for(re int i=0;i<tttttt;i++)
    63     {
    64         int all=(~i)&(tttttt-1);
    65         for(re int k=all;k;k=(k-1)&all)
    66         {
    67             int cnt=0;
    68             for(re int j=k;j;j-=(j&-j))
    69                 cnt+=tem[i][g[j&-j]];
    70             
    71             if(siz[k]&1)f[i|k]=(f[i|k]+f[i]*pw[cnt]%mod);
    72             else         f[i|k]=(f[i|k]-f[i]*pw[cnt]%mod);
    73             if(f[i|k]<0)f[i|k]=f[i|k]%mod+mod;
    74             if(f[i|k]>=mod)f[i|k]-=mod;
    75         }
    76     }
    77     
    78     printf("%lld
    ",(f[(1<<n)-1]%mod+mod)%mod);
    79 }
    80 inline void add(rec int u,rec int v)
    81 {
    82     ++num_e;
    83     u(num_e)=u;
    84     v(num_e)=v;
    85     n(num_e)=f(u);
    86     f(u)=num_e;
    87 }
    88 LL poww(LL a,int b)
    89 {    
    90     LL ans=1;
    91     while(b)
    92     {    
    93         if(b&1)ans=ans*a%mod;
    94         a=a*a%mod;b=b>>1;
    95     }
    96     return ans;
    97 }
    View Code
  • 相关阅读:
    idea中如何返回上一个鼠标的焦点
    git-修改本地和远端分支名字
    git修改已经commit的注释记录
    《完全用Linux工作》
    C++ 网络爬虫实现
    计算两个YUV420P像素数据的PSNR---高等算法
    C++类对象大小的计算
    mp4文件格式解析
    BMP图片格式模型(2)
    BMP图片格式模型
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11619314.html
Copyright © 2011-2022 走看看