【CF908E】New Year and Entity Enumeration 位元運算+DP

來源:互聯網
上載者:User

標籤:ati   好的   print   char s   include   取反   ios   clu   哪些   

【CF908E】New Year and Entity Enumeration

題意:給定$M=2^m-1$,我們稱一個集合S是好的,若且唯若它滿足:1.$\forall a\in S,a \mathrm{xor} M \in S$,2.$\forall a,b\in S,a \mathrm{and} b \in S$,3.\forall a\in S,a\le M。

現在給定集合T,求有多少個好的集合S,滿足T是S的子集。

m<=1000,|T|<=50。

題解:顯然有了與和取反以後,我們還可以實現或和異或。如果給定T以後,我們對T中的數進行運算能得到什麼數呢?容易發現如果二進位位a和位b如果在所有數中都是相同的,那麼造出來的數也一定滿足位a和位b是相同的。所有滿足這個條件的數我們都能造出來。

也就是說,我們只需要確定S中哪些位是始終相同的,即把m個物品分到若干個集合的方案數(Bell數),用$m^2$的DP很容易求出。

但是由於要求T是S的子集,相當於認為的將某些物品分到了一起,我們可以對每個位置維護一個|T|位二進位狀態,如果兩個位置的狀態是不同的,則這兩個位置不是始終相同的,則S中對應位置也不能始終相同。所以我們可以對所有相同的狀態,代入Bell數求出方案,再將不同狀態的方案數乘到一起即可。

 

#include <cstdio>#include <cstring>#include <iostream>using namespace std;typedef long long ll;const ll P=1000000007;bool ban[1010][1010];int bel[1010];int n,m;ll ans;ll tag[1010],f[1010][1010],s[1010];char str[1010];int main(){scanf("%d%d",&m,&n);int i,j,siz;for(i=1;i<=n;i++){scanf("%s",str+1);for(j=1;j<=m;j++)if(str[j]==‘1‘)tag[j]|=1ll<<(i-1);}ans=f[0][0]=1;for(i=1;i<=m;i++)for(j=1;j<=i;j++)f[i][j]=(f[i-1][j]*j+f[i-1][j-1])%P,s[i]=(s[i]+f[i][j])%P;for(i=1;i<=m;i++)if(!bel[i]){siz=0;for(j=i;j<=m;j++)if(tag[j]==tag[i])bel[j]=i,siz++;ans=ans*s[siz]%P;}printf("%lld",ans);return 0;}

 

【CF908E】New Year and Entity Enumeration 位元運算+DP

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.