CF1221G Graph And Number (inclusion and exclusion, search, the FMT)

Edu think this has to be simpler than the G EF ......

I do not know why people make the topic \ (m = 0 \) into them, especially the first sentence out.

It requires at least one \ (0 \) , at least one \ (1 \) , at least one \ (2 \) , inclusion and exclusion wave, into the total number of programs - None \ (0 \) - None \ (1 \) - no \ (2 \) + no \ (01 \) + no \ (02 \) + no \ (12 \) + no \ (012 \) .

No \ (0 \) and no \ (2 \) compare downright, put the final discussion.

No \ (1 \) , consider a link block, the link block all numbers are the same, the program number is \ (CNT 2 ^ {} \) , where \ (CNT \) is the number of blocks of China Unicom.

No \ (01 \) , which is only \ (2 \) , if a link does not block side (single point), then of course you can easily put, otherwise the Unicom block all numbers are \ (1 \) . Program Number \ (CNT2 2 ^ {} \) , where \ (\ CNT2) is the number of blocks of a single point of China Unicom.

No \ (02 \) , which is only \ (1 \) , this figure is equivalent to the number of black and white coloring scheme. If dyed black and white, then the program number is \ (CNT 2 ^ {} \) , otherwise \ (0 \) .

No \ (12 \) , and no \ (01 \) the same. Program numbers are \ (CNT2 2 ^ {} \) .

No \ (012 \) , since \ (m \ NE 0 \) , is clearly impossible. Program number \ (0 \) .

Then consider no (0 \) \ program number (no \ (2 \) is the same).

The data range is clearly let us binary search. We may wish to search the second half.

For the second half of each valid (that is, no two are \ (0 \) of adjacent points), the first part of what point can not be \ (0 \) we know.

Change it into half of the current selected \ (0 \) point set to \ (S \) , the second half of the number of kinds of programs \ (val_S \) . (This is what I wrote)

Satisfying the condition (S \) \ is the complement of the subset of points can not be selected.

In fact, the complement of \ (val \) add a \ (1 \) , do it after the high-dimensional search suffix and can get really \ (val_S \) . It should not be difficult to understand.

And then search the first half, for every legal schemes coupled with its \ (val \) on the line.

Time complexity, if the front half portion having \ (T \) points complexity is \ (O (TT ^ 2 + 2 ^ {nT}) \) .

Since I lazy, I took \ (T = \ FRAC {n-2}} {\) . In fact, if \ (T \) controlled well enough, should be ran \ (n-50 = \) . (Take \ (T = 23 \) , probably 3e8,3.5s + CF God machine should be no problem)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=1048576;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
    char ch=getchar();ll x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int n,m,cnt,cnt2,bar,lim;
ll e[40],ans,val[maxn];
bool ind[40],vis[40],col[40],flag=true;
void dfs(int u){
    vis[u]=true;
    FOR(v,0,n-1) if((e[u]>>v)&1){
        if(!vis[v]) col[v]=col[u]^1,dfs(v);
        else{
            if(col[v]!=(col[u]^1)) flag=false;
        }
    }
}
void dfs1(int dep,ll st,ll used){
    if(dep==bar) return void(val[(~st)&(lim-1)]++);
    dfs1(dep-1,st,used);
    if(!((st>>dep)&1)) dfs1(dep-1,st|e[dep],used|1<<dep);
}
void dfs2(int dep,ll st,ll used){
    if(dep==bar+1) return void(ans-=2*val[used&(lim-1)]);
    dfs2(dep+1,st,used);
    if(!((st>>dep)&1)) dfs2(dep+1,st|e[dep],used|1<<dep);
}
int main(){
    n=read();m=read();
    if(!m) return puts("0"),0;
    FOR(i,0,n-1) ind[i]=true;
    FOR(i,1,m){
        int u=read()-1,v=read()-1;
        e[u]|=1ll<<v;e[v]|=1ll<<u;
        ind[u]=ind[v]=false;
    }
    FOR(i,0,n-1) if(ind[i]) cnt2++;
    FOR(i,0,n-1) if(!vis[i]) cnt++,dfs(i);
    ans=(1ll<<n)-(1ll<<cnt)+(1ll<<cnt2)+(1ll<<cnt2)+(flag?1ll<<cnt:0);
    bar=(n-1)/2;lim=1<<(bar+1);
    dfs1(n-1,0,0);
    for(int i=1;i<lim;i<<=1)
        for(int j=0;j<lim;j+=i<<1)
            FOR(k,0,i-1) val[j+k]+=val[i+j+k];
    dfs2(0,0,0);
    printf("%lld\n",ans);
}

Guess you like

Origin www.cnblogs.com/1000Suns/p/11566940.html