COCI2011:友好数对

时间:2021-07-27 20:16:38

校内OJ传送门

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

然后复杂度就爆炸了。

小优化:

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

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

下面是代码的具体实现。

 //OJ 1376
 //by Cydiater
 //2016.9.18
 #include <iostream>
 #include <cstdio>
 #include <cstring>
 #include <string>
 #include <algorithm>
 #include <queue>
 #include <map>
 #include <ctime>
 #include <cmath>
 #include <iomanip>
 #include <cstdlib>
 using namespace std;
 #define ll long long
 #define up(i,j,n)        for(int i=j;i<=n;i++)
 #define down(i,j,n)        for(int i=j;i>=n;i--)
 <<;
 const int oo=0x3f3f3f3f;
 inline ll read(){
     ,f=;
     ;ch=getchar();}
     +ch-';ch=getchar();}
     return x*f;
 }
 ll N,T[MAXN],num,ans=,f[MAXN];
 namespace solution{
     void init(){
         N=read();
         memset(f,,sizeof(f));
         up(i,,N){
             ll S=;num=read();
             ){
                 ;
                 S|=(<<tmp);
                 num/=;
             }
             T[S]++;
         }
         up(i,,(<<)-)up(j,,(<<)-)if((j&i)==j)f[j]+=T[i];
         up(i,,(<<)-)f[i]=(f[i]-)*f[i]/;
     }
     void slove(){
         up(s,,(<<)-){
             ;
             up(i,,)<<i))cnt++;
             )ans+=f[s];
             else     ans-=f[s];
         }
     }
     void output(){
         cout<<ans<<endl;
     }
 }
 int main(){
     //freopen("input.in","r",stdin);
     using namespace solution;
     init();
     slove();
     output();
     ;
 }