zoukankan      html  css  js  c++  java
  • BZOJ4671: 异或图

    $1 leq s leq 60$个$2 leq n leq 10$的图,定义图的异或是:如果一条边在两个图中出现次数和为1,那么异或后的图中存在这条边,否则不存在。问有多少图的集合满足异或后的图是连通图。

    暂时自己推不动的题系列QAQ

    容斥一发,枚举点集划分,然后强行让在不同点集的点不连边而同一点集内的点随意。如此一来,假如有一种真实的方案,它把图真真切切的变成了$m$个连通块,那么这种方案会被统计$sum_{i=1}^megin{Bmatrix} m \  i end{Bmatrix}$次,就是,每次把分完的点集合再拿去分集合,然后会分到若干大集合,然后因为大集合里的点是乱连的,所以会算到这种情况。需要系数$f(i)$,满足$sum_{i=1}^megin{Bmatrix} m \  i end{Bmatrix} f(i)=[m=1]$。

    用斯特林数递推求这个系数当然没问题,但打表后可得$f(i)=(-1)^{i-1}(i-1)!$,简要证明:

    $sum_{i=1}^{m}egin{Bmatrix} m\ iend{Bmatrix}(-1)^{i-1}(i-1)!$
    $\ =sum_{i=1}^{m}(-1)^{i-1}(i-1)!(egin{Bmatrix} m-1\ i-1end{Bmatrix}+iegin{Bmatrix} m-1\ iend{Bmatrix})$
    $\ =sum_{i=1}^{m}(-1)^{i-1}(i-1)!egin{Bmatrix} m-1\ i-1end{Bmatrix}+sum_{i=1}^{m}(-1)^{i-1}i!egin{Bmatrix} m-1\ iend{Bmatrix}$
    $\ =sum_{i=0}^{m-1}(-1)^ii!egin{Bmatrix} m-1\ iend{Bmatrix}+sum_{i=1}^{m-1}(-1)^{i-1}i!egin{Bmatrix} m-1\ iend{Bmatrix}$
    $\ =[m=1]$

    好的0.0

    然后一个点集划分怎么求满足的方案呢,把要的那几位提出来丢线性基里,异或出0的方案数就是$2^{S-cnt}$,$cnt$是线性基的大小。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<math.h>
     5 //#include<time.h>
     6 //#include<complex>
     7 //#include<set>
     8 //#include<queue>
     9 #include<algorithm>
    10 #include<stdlib.h>
    11 using namespace std;
    12 
    13 #define LL long long
    14 int qread()
    15 {
    16     char c; int s=0; while ((c=getchar())<'0' || c>'9');
    17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s;
    18 }
    19 
    20 //Pay attention to '-' , LL and double of qread!!!!
    21 
    22 int n,S;
    23 LL ans,f[22],a[66],b[66],two[66]; int list[22][22],len[22],bel[22];
    24 
    25 struct JI
    26 {
    27     LL a[66]; int n,m;
    28     void clear(int mm) {m=mm; n=0; memset(a,0,sizeof(a));}
    29     void insert(LL v)
    30     {
    31         for (int i=m;~i;i--) if ((v>>i)&1)
    32         {
    33             if (!a[i]) {a[i]=v; n++; break;}
    34             v^=a[i];
    35         }
    36     }
    37 }ji;
    38 
    39 void calc(int tot)
    40 {
    41     memset(b,0,sizeof(b));
    42     int lb=0;
    43     for (int i=1,pp=0;i<=n;i++)
    44         for (int j=i+1;j<=n;j++,pp++)
    45             if (bel[i]!=bel[j])
    46             {
    47                 for (int k=1;k<=S;k++) b[k]|=((a[k]>>pp)&1)<<lb;
    48                 lb++;
    49             }
    50     ji.clear(lb-1);
    51     for (int i=1;i<=S;i++) ji.insert(b[i]);
    52     ans+=f[tot]*two[S-ji.n];
    53 }
    54     
    55 void dfs(int cur,int tot)
    56 {
    57     if (cur>n) {calc(tot); return;}
    58     for (int i=1;i<=tot;i++)
    59     {
    60         bel[cur]=i;
    61         list[i][++len[i]]=cur;
    62         dfs(cur+1,tot);
    63         len[i]--;
    64     }
    65     bel[cur]=tot+1;
    66     list[tot+1][++len[tot+1]]=cur;
    67     dfs(cur+1,tot+1);
    68     len[tot+1]--;
    69 }
    70 
    71 char s[55];
    72 int main()
    73 {
    74     S=qread();
    75     for (int i=1;i<=S;i++)
    76     {
    77         scanf("%s",s); int m=strlen(s);
    78         n=(int)(sqrt(1+8*m)+1.1)>>1;
    79         for (int j=0;j<m;j++) a[i]|=(LL)(s[j]=='1')<<j;
    80     }
    81     
    82     {
    83         LL fac=1; int fu=1;
    84         for (int i=1;i<=n;i++)
    85         {
    86             f[i]=fac*fu;
    87             fu=-fu; fac*=i;
    88         }
    89         two[0]=1; for (int i=1;i<=S;i++) two[i]=two[i-1]<<1;
    90     }
    91     
    92     ans=0; dfs(1,0);
    93     printf("%lld
    ",ans);
    94     return 0;
    95 }
    View Code
  • 相关阅读:
    NET C#测试程序运行时间
    openGL 高程配色绘制点云(csGL)
    openGL 绘制文本font(csGL)
    openGL 选择和反馈(csGL)
    简单实现angular2组件双向绑定
    angular2 ChangeDetectorRef (变化检测器的引用)手动控制组件的变化检测行为
    Angular 2 Forward Reference (可用作获取父组件对象)
    两个iframe之间tab切换,谷歌浏览器的滚动条会消失
    js随机从数组中取出几个元素
    原生js javascript 实现trigger(自动触发window 的resize事件)
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8927184.html
Copyright © 2011-2022 走看看