首页 > 代码库 > COCI2011:友好数对

COCI2011:友好数对

校内OJ传送门

 

一般容斥,具体思想参考代码实现,刚开始是在读入时处理所有数的二进制子集,没看$N$的范围以为复杂度不会爆炸..

然后复杂度就爆炸了。

小优化:

每次整个载入二进制,计数。这个结束后枚举计数的状态和答案的状态。

up(i,1,(1<<10)-1)up(j,1,(1<<10)-1)if((j&i)==j)f[j]+=T[i];up(i,1,(1<<10)-1)f[i]=(f[i]-1)*f[i]/2;

下面是代码的具体实现。

技术分享
 1 //OJ 1376 2 //by Cydiater 3 //2016.9.18 4 #include <iostream> 5 #include <cstdio> 6 #include <cstring> 7 #include <string> 8 #include <algorithm> 9 #include <queue>10 #include <map>11 #include <ctime>12 #include <cmath>13 #include <iomanip>14 #include <cstdlib>15 using namespace std;16 #define ll long long17 #define up(i,j,n)        for(int i=j;i<=n;i++)18 #define down(i,j,n)        for(int i=j;i>=n;i--)19 const int MAXN=1<<15;20 const int oo=0x3f3f3f3f;21 inline ll read(){22     char ch=getchar();ll x=0,f=1;23     while(ch>9||ch<0){if(ch==-)f=-1;ch=getchar();}24     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}25     return x*f;26 }27 ll N,T[MAXN],num,ans=0,f[MAXN];28 namespace solution{29     void init(){30         N=read();31         memset(f,0,sizeof(f));32         up(i,1,N){33             ll S=0;num=read();34             while(num>0){35                 int tmp=num%10;36                 S|=(1<<tmp);37                 num/=10;38             }39             T[S]++;40         }41         up(i,1,(1<<10)-1)up(j,1,(1<<10)-1)if((j&i)==j)f[j]+=T[i];42         up(i,1,(1<<10)-1)f[i]=(f[i]-1)*f[i]/2;43     }44     void slove(){45         up(s,1,(1<<10)-1){46             int cnt=0;47             up(i,0,9)if(s&(1<<i))cnt++;48             if(cnt%2)ans+=f[s];49             else     ans-=f[s];50         }51     }52     void output(){53         cout<<ans<<endl;54     }55 }56 int main(){57     //freopen("input.in","r",stdin);58     using namespace solution;59     init();60     slove();61     output();62     return 0;63 }
View Code

 

COCI2011:友好数对