zoukankan      html  css  js  c++  java
  • Sets 比赛时想错方向了。。。。 (大数不能处理负数啊)

     Sets

    Time Limit: 6000/3000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
    SubmitStatus

    Problem Description

    给出N个数,现在需要将这些数分成若干个不相交的集合,同时给出M个限制集合,使得划分成的集合中,不能有任何一个集合包含给出的M个集合中的任意一个。求有多少种合法的集合划分方案

    Input

    多组数据,每组数据 :

    第一行N,M(1 <= N <= 100,0 <= M <= 10)

    接下来M行,每行开始一个数TOT,表示这个禁止集合中的元素个数,接下来有TOT个数。(1 <= TOT <= N,且TOT个数都是1-N之间的正整数)

    Output

    每组数据,输出一行,你的答案

    Sample Input

    2 0
    3 2
    2 1 2
    2 1 3
    10 0
    

    Sample Output

    2
    2
    115975

    Hint

    第二个样例:

    3个数的划分方案是 :

    {1} {2} {3}

    {1,2} {3}

    {1,3} {2}

    {1} {2,3}

    {1,2,3}

    因为划分方案中任意一组合法划分不能有一个集合包含 {1,2}或 {1,3}作为子集,所以"{1,2} {3}","{1,3} {2}", "{1,2,3}"这3种划分方案不合法,合法方案为2

      1 #include <iostream>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <math.h>
      5 #include <stdio.h>
      6 using namespace std;
      7 
      8 #define MAXN 9999
      9 #define MAXSIZE 10
     10 #define DLEN 4
     11 
     12 class BigNum
     13 {
     14 private:
     15     int a[500];    //可以控制大数的位数
     16     int len;       //大数长度
     17 public:
     18     BigNum()
     19     {
     20         len = 1;    //构造函数
     21         memset(a,0,sizeof(a));
     22     }
     23     BigNum(const int);       //将一个int类型的变量转化为大数
     24     BigNum(const char*);     //将一个字符串类型的变量转化为大数
     25     BigNum(const BigNum &);  //拷贝构造函数
     26     BigNum &operator=(const BigNum &);   //重载赋值运算符,大数之间进行赋值运算
     27 
     28     friend istream& operator>>(istream&,  BigNum&);   //重载输入运算符
     29     friend ostream& operator<<(ostream&,  BigNum&);   //重载输出运算符
     30 
     31     BigNum operator+(const BigNum &) const;   //重载加法运算符,两个大数之间的相加运算
     32     BigNum operator-(const BigNum &) const;   //重载减法运算符,两个大数之间的相减运算
     33     BigNum operator*(const BigNum &) const;   //重载乘法运算符,两个大数之间的相乘运算
     34     BigNum operator/(const int   &) const;    //重载除法运算符,大数对一个整数进行相除运算
     35 
     36     BigNum operator^(const int  &) const;    //大数的n次方运算
     37     int    operator%(const int  &) const;    //大数对一个int类型的变量进行取模运算
     38     bool   operator>(const BigNum & T)const;   //大数和另一个大数的大小比较
     39     bool   operator>(const int & t)const;      //大数和一个int类型的变量的大小比较
     40 
     41     void print();       //输出大数
     42 };
     43 BigNum::BigNum(const int b)     //将一个int类型的变量转化为大数
     44 {
     45     int c,d = b;
     46     len = 0;
     47     memset(a,0,sizeof(a));
     48     while(d > MAXN)
     49     {
     50         c = d - (d / (MAXN + 1)) * (MAXN + 1);
     51         d = d / (MAXN + 1);
     52         a[len++] = c;
     53     }
     54     a[len++] = d;
     55 }
     56 BigNum::BigNum(const char*s)     //将一个字符串类型的变量转化为大数
     57 {
     58     int t,k,index,l,i;
     59     memset(a,0,sizeof(a));
     60     l=strlen(s);
     61     len=l/DLEN;
     62     if(l%DLEN)
     63         len++;
     64     index=0;
     65     for(i=l-1; i>=0; i-=DLEN)
     66     {
     67         t=0;
     68         k=i-DLEN+1;
     69         if(k<0)
     70             k=0;
     71         for(int j=k; j<=i; j++)
     72             t=t*10+s[j]-'0';
     73         a[index++]=t;
     74     }
     75 }
     76 BigNum::BigNum(const BigNum & T) : len(T.len)  //拷贝构造函数
     77 {
     78     int i;
     79     memset(a,0,sizeof(a));
     80     for(i = 0 ; i < len ; i++)
     81         a[i] = T.a[i];
     82 }
     83 BigNum & BigNum::operator=(const BigNum & n)   //重载赋值运算符,大数之间进行赋值运算
     84 {
     85     int i;
     86     len = n.len;
     87     memset(a,0,sizeof(a));
     88     for(i = 0 ; i < len ; i++)
     89         a[i] = n.a[i];
     90     return *this;
     91 }
     92 istream& operator>>(istream & in,  BigNum & b)   //重载输入运算符
     93 {
     94     char ch[MAXSIZE*4];
     95     int i = -1;
     96     in>>ch;
     97     int l=strlen(ch);
     98     int count=0,sum=0;
     99     for(i=l-1; i>=0;)
    100     {
    101         sum = 0;
    102         int t=1;
    103         for(int j=0; j<4&&i>=0; j++,i--,t*=10)
    104         {
    105             sum+=(ch[i]-'0')*t;
    106         }
    107         b.a[count]=sum;
    108         count++;
    109     }
    110     b.len =count++;
    111     return in;
    112 
    113 }
    114 ostream& operator<<(ostream& out,  BigNum& b)   //重载输出运算符
    115 {
    116     int i;
    117     cout << b.a[b.len - 1];
    118     for(i = b.len - 2 ; i >= 0 ; i--)
    119     {
    120         cout.width(DLEN);
    121         cout.fill('0');
    122         cout << b.a[i];
    123     }
    124     return out;
    125 }
    126 
    127 BigNum BigNum::operator+(const BigNum & T) const   //两个大数之间的相加运算
    128 {
    129     BigNum t(*this);
    130     int i,big;      //位数
    131     big = T.len > len ? T.len : len;
    132     for(i = 0 ; i < big ; i++)
    133     {
    134         t.a[i] +=T.a[i];
    135         if(t.a[i] > MAXN)
    136         {
    137             t.a[i + 1]++;
    138             t.a[i] -=MAXN+1;
    139         }
    140     }
    141     if(t.a[big] != 0)
    142         t.len = big + 1;
    143     else
    144         t.len = big;
    145     return t;
    146 }
    147 BigNum BigNum::operator-(const BigNum & T) const   //两个大数之间的相减运算
    148 {
    149     int i,j,big;
    150     bool flag;
    151     BigNum t1,t2;
    152     if(*this>T)
    153     {
    154         t1=*this;
    155         t2=T;
    156         flag=0;
    157     }
    158     else
    159     {
    160         t1=T;
    161         t2=*this;
    162         flag=1;
    163     }
    164     big=t1.len;
    165     for(i = 0 ; i < big ; i++)
    166     {
    167         if(t1.a[i] < t2.a[i])
    168         {
    169             j = i + 1;
    170             while(t1.a[j] == 0)
    171                 j++;
    172             t1.a[j--]--;
    173             while(j > i)
    174                 t1.a[j--] += MAXN;
    175             t1.a[i] += MAXN + 1 - t2.a[i];
    176         }
    177         else
    178             t1.a[i] -= t2.a[i];
    179     }
    180     t1.len = big;
    181     while(t1.a[len - 1] == 0 && t1.len > 1)
    182     {
    183         t1.len--;
    184         big--;
    185     }
    186     if(flag)
    187         t1.a[big-1]=0-t1.a[big-1];
    188     return t1;
    189 }
    190 
    191 BigNum BigNum::operator*(const BigNum & T) const   //两个大数之间的相乘运算
    192 {
    193     BigNum ret;
    194     int i,j,up;
    195     int temp,temp1;
    196     for(i = 0 ; i < len ; i++)
    197     {
    198         up = 0;
    199         for(j = 0 ; j < T.len ; j++)
    200         {
    201             temp = a[i] * T.a[j] + ret.a[i + j] + up;
    202             if(temp > MAXN)
    203             {
    204                 temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
    205                 up = temp / (MAXN + 1);
    206                 ret.a[i + j] = temp1;
    207             }
    208             else
    209             {
    210                 up = 0;
    211                 ret.a[i + j] = temp;
    212             }
    213         }
    214         if(up != 0)
    215             ret.a[i + j] = up;
    216     }
    217     ret.len = i + j;
    218     while(ret.a[ret.len - 1] == 0 && ret.len > 1)
    219         ret.len--;
    220     return ret;
    221 }
    222 BigNum BigNum::operator/(const int & b) const   //大数对一个整数进行相除运算
    223 {
    224     BigNum ret;
    225     int i,down = 0;
    226     for(i = len - 1 ; i >= 0 ; i--)
    227     {
    228         ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
    229         down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
    230     }
    231     ret.len = len;
    232     while(ret.a[ret.len - 1] == 0 && ret.len > 1)
    233         ret.len--;
    234     return ret;
    235 }
    236 int BigNum::operator %(const int & b) const    //大数对一个int类型的变量进行取模运算
    237 {
    238     int i,d=0;
    239     for (i = len-1; i>=0; i--)
    240     {
    241         d = ((d * (MAXN+1))% b + a[i])% b;
    242     }
    243     return d;
    244 }
    245 BigNum BigNum::operator^(const int & n) const    //大数的n次方运算
    246 {
    247     BigNum t,ret(1);
    248     int i;
    249     if(n<0)
    250         exit(-1);
    251     if(n==0)
    252         return 1;
    253     if(n==1)
    254         return *this;
    255     int m=n;
    256     while(m>1)
    257     {
    258         t=*this;
    259         for( i=1; i<<1<=m; i<<=1)
    260         {
    261             t=t*t;
    262         }
    263         m-=i;
    264         ret=ret*t;
    265         if(m==1)
    266             ret=ret*(*this);
    267     }
    268     return ret;
    269 }
    270 bool BigNum::operator>(const BigNum & T) const   //大数和另一个大数的大小比较
    271 {
    272     int ln;
    273     if(len > T.len)
    274         return true;
    275     else if(len == T.len)
    276     {
    277         ln = len - 1;
    278         while(a[ln] == T.a[ln] && ln >= 0)
    279             ln--;
    280         if(ln >= 0 && a[ln] > T.a[ln])
    281             return true;
    282         else
    283             return false;
    284     }
    285     else
    286         return false;
    287 }
    288 bool BigNum::operator >(const int & t) const    //大数和一个int类型的变量的大小比较
    289 {
    290     BigNum b(t);
    291     return *this>b;
    292 }
    293 
    294 void BigNum::print()    //输出大数
    295 {
    296     int i;
    297     cout << a[len - 1];
    298     for(i = len - 2 ; i >= 0 ; i--)
    299     {
    300         cout.width(DLEN);
    301         cout.fill('0');
    302         cout << a[i];
    303     }
    304 }
    305 BigNum dp[110][110];
    306 void init()
    307 {
    308     int i,j;
    309     dp[0][0]=1;
    310     for(i=1; i<110; i++)
    311     {
    312         dp[i][0]=0;
    313         for(j=1; j<=i; j++)
    314             dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1];
    315     }
    316     for(i=1; i<110; i++)
    317     {
    318         for(j=1; j<=i; j++)
    319             dp[i][0]=dp[i][0]+dp[i][j];
    320     }
    321     dp[0][0]=0;
    322 }
    323 int a[20][110],n,m;
    324 int father[200];
    325 BigNum ans,ans1;
    326 int findfa(int x)
    327 {
    328     return father[x] == x ? x : father[x] = findfa(father[x]);
    329 }
    330 void solve(int x)
    331 {
    332     int i,j,y,z,nm=n;
    333     bool bi=0;
    334     for(i=1; i<=n; i++)father[i]=i;
    335     for(i=0; i<m; i++)
    336     {
    337         if(x&(1<<i))
    338         {
    339             bi^=1;
    340             if(a[i][0]==0)continue;
    341             y=findfa(a[i][1]);
    342             for(j=2; j<=a[i][0]; j++)
    343             {
    344                 z=findfa(a[i][j]);
    345                 if(z!=y)
    346                     father[z]=y,nm--;
    347             }
    348         }
    349     }
    350     if(bi)ans1=ans1+dp[nm][0];
    351     else ans=ans+dp[nm][0];
    352 }
    353 void work()
    354 {
    355     int i,j,len=(1<<m);
    356     ans1=ans=0;
    357     for(i=0; i<len; i++)
    358     {
    359         solve(i);
    360     }
    361     ans=ans-ans1;
    362     ans.print();
    363     printf("
    ");
    364 }
    365 int main(void)
    366 {
    367     init();
    368     int i,j;
    369     while(~scanf("%d%d",&n,&m))
    370     {
    371         for(i=0; i<m; i++)
    372         {
    373             scanf("%d",&a[i][0]);
    374             for(j=1; j<=a[i][0]; j++)
    375                 scanf("%d",&a[i][j]);
    376         }
    377         work();
    378     }
    379 }
    View Code
  • 相关阅读:
    JSP的作用域与COOKIE
    jsp数据交互
    JSP基本使用方式
    分层架构的初步理解
    JDBC的基本应用
    HTML5新标签
    弹性布局
    解决js获取兄弟节点的兼容问题
    js去重函数(封装函数)
    封装日期函数
  • 原文地址:https://www.cnblogs.com/ERKE/p/3867551.html
Copyright © 2011-2022 走看看