zoukankan      html  css  js  c++  java
  • CoFun 1612 单词分组(容斥)

    Description

    Stan有N个不同的单词,这天,Stan新结交的两个朋友来他这里玩,Stan作为主人,他需要送给他们单词,但由于Stan不能偏心,所以Stan给每个单词一个权值v_i,他需要他这N个单词恰好分配给这两个朋友,这个地方的人很奇怪,他们用来定义自己的喜悦值的方式是把所有得到的单词的权值都位运算and起来的值,所以你需要使得两个朋友的喜悦值是相同的

    好学的Stan不满足于求出一种方案,而是想要知道总共有多少种方案数,Stan觉得这个太简单了,所以请你来帮他解决吧。

    Input Format

    第一行包含一个整数N

    第二行包含N个非负整数,表示每个单词的权值

    Output Format

    输出仅一行,即方案数

     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 #define ll long long
     7 ll f[2][1025][1025][2][2],ans=0;
     8 int n,a[1025],mx,bin[30];
     9 int b[55][105],m,num,fa[105];
    10 int read(){
    11     char ch=getchar();int t=0,f=1;
    12     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    13     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
    14     return t*f;
    15 }
    16 void sbpianfen(){
    17     for (int i=1;i<=n;i++){
    18         int now=i&1,pre=now^1;
    19         if (i==1){
    20             f[now][a[i]][0][1][0]=1;
    21             f[now][0][a[i]][0][1]=1;
    22             continue;
    23         }
    24         for (int j=0;j<=mx;j++) for (int k=0;k<=mx;k++) for (int l=0;l<=1;l++) for (int z=0;z<=1;z++) f[now][j][k][l][z]=0;
    25         for (int j=0;j<=mx;j++)
    26          for (int k=0;k<=mx;k++){
    27             if (k==0)
    28              f[now][j&a[i]][k][1][0]+=f[pre][j][k][1][0];
    29             f[now][j&a[i]][k][1][1]+=f[pre][j][k][1][1];
    30             if (j==0)
    31              f[now][j][k&a[i]][0][1]+=f[pre][j][k][0][1];
    32             f[now][j][k&a[i]][1][1]+=f[pre][j][k][1][1]; 
    33          }
    34         for (int j=0;j<=mx;j++){
    35          f[now][a[i]][j][1][1]+=f[pre][0][j][0][1];
    36          f[now][j][a[i]][1][1]+=f[pre][j][0][1][0];
    37         } 
    38     }
    39     ans=0;
    40     for (int i=0;i<=mx;i++)
    41      ans+=f[n&1][i][i][1][1];
    42     printf("%lld
    ",ans); 
    43 }
    44 int find(int x){
    45     if (fa[x]==x) return x;
    46     else return (fa[x]=find(fa[x]));
    47 }
    48 void dfs(int dep,int delta){
    49     if (dep==m){
    50         ans+=(ll)delta*(((ll)1<<num));
    51         return;
    52     }
    53     dfs(dep+1,delta);
    54     int tnum=num;
    55     int tmp[51];
    56     for (int j=0;j<n;j++) tmp[j]=fa[j];
    57     int T;
    58     for (T=0;!b[dep][T];T++);
    59     int f=find(T);
    60     for (int j=T+1;j<n;j++)
    61       if (b[dep][j]){
    62             int xx=find(j);
    63             if (xx!=f){
    64                 fa[xx]=f;
    65                 num--;
    66             }
    67       }
    68     dfs(dep+1,-delta);
    69     for (int j=0;j<n;j++)
    70      fa[j]=tmp[j];
    71     num=tnum;   
    72 }
    73 void sxpianfen(){
    74     m=0;
    75     for (int i=0;i<20;i++){
    76         int t=1<<i,cnt=0;
    77         for (int j=0;j<n;j++)
    78          if (a[j]&t) cnt++;
    79         if (cnt==0||cnt==n) continue;
    80         for (int j=0;j<n;j++)
    81          if (!(a[j]&t)) b[m][j]=1;
    82          else b[m][j]=0;
    83         m++; 
    84     }
    85     for (int i=0;i<n;i++)
    86      b[m][i]=1,fa[i]=i;
    87     m++; 
    88     ans=0;
    89     num=n; 
    90     dfs(0,1);
    91     printf("%lld
    ",ans); 
    92 }
    93 int main(){
    94     n=read();
    95     for (int i=0;i<n;i++) a[i]=read();
    96     sxpianfen();
    97 }
  • 相关阅读:
    月食照片
    宾得镜头大全与发展史
    月食照片
    关于镜头系数的疑问
    经验和教训
    常用正则表达式
    12月19日
    部長面談
    周六
    异度空间
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5550223.html
Copyright © 2011-2022 走看看