题目:

 

 

 

 

暴搜30分

#include<bits/stdc++.h>
using namespace std;
#define N 100005
int n,m,ans=0,maxn;
bool vis[1<<21];
struct node{
    int l,r;
}v[N];
int read()
{
    int x=0,fl=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') fl=-1; ch=getchar(); }
    while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=getchar();
    return x*fl;
}
int change(int x,int l,int r)
{
    for(int i=l;i<=r;++i) x=x^(1<<(n-i));
    return x;
}
void dfs(int pos,int x)
{
    if(ans>=maxn) { printf("%d\n",maxn); exit(0); }
    if(pos>m){//printf("x:%d\n",x);
        if(!vis[x]) ans++,vis[x]=true; 
        return ;
    }
    dfs(m+1,x);
    for(int i=pos;i<=m;i++){
        int tmp=change(x,v[i].l,v[i].r);
        dfs(i+1,tmp);
    }
}
int quick_pow(int a,int k)
{
    int ans=1;
    while(k){ if(k&1) ans*=a; a*=a; k>>=1; }
    return ans;
}
int main()
{
    freopen("seg.in","r",stdin);
    freopen("seg.out","w",stdout);
    n=read(); m=read();
    for(int i=1;i<=m;++i) v[i].l=read(),v[i].r=read();
    maxn=quick_pow(2,n);
    dfs(1,0);
    printf("%d\n",ans);
    return 0;
}
/*
3 3
1 1
2 2
3 3
*/
View Code

分析:

如果每一个点都可以翻转的话,就是2^n种,再推广一下,如果不考虑重复的话,就是2^m种。

但是像 1 2 , 3 4,1 4,这三个区间,第三个明显可以由第一个和第二个拼凑而来,就会多算一种。

考虑删除无用区间:并查集合并区间

具体步骤:将一个区间的左端点和右端点+1放在一起,如果已经是同一个father了,就说明已经合并在一起了,即为无用区间。(father同,说明左端点和右端点早已连在了同一个点上)

(其实可以不用排序,因为1 2,1 4 是可以凑出3 4的,不一定要小的凑大的)

#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define ll long long
const int mod=1e9+7;
int n,m,fa[N],tmp[N];
ll ans=0;
struct node{
    int l,r;
}v[N];
bool cmp(const node &a,const node &b)
{
    return (a.r-a.l)<(b.r-b.l);
}
int read()
{
    int x=0,fl=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') fl=-1; ch=getchar(); }
    while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=getchar();
    return x*fl;
}

ll quick_pow(int a,int k)
{
    ll ans=1;
    while(k){ if(k&1) ans=(ll)ans*a%mod; a=(ll)a*a%mod; k>>=1; }
    return ans;
}
int find(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}
int main()
{
    freopen("seg.in","r",stdin);
    freopen("seg.out","w",stdout);
    n=read(); m=read();
    
    for(int i=1;i<=n+1;i++) fa[i]=i;
    for(int i=1;i<=m;++i) v[i].l=read(),v[i].r=read();
    //sort(v+1,v+1+m,cmp);
    int cnt=m;
    for(int i=1;i<=m;i++){
        int f1=find(v[i].l),f2=find(v[i].r+1);
        if(f1==f2) cnt--;
        else fa[f1]=f2;
    }
    printf("%d\n",cnt);
    ans=quick_pow(2,cnt);
    printf("%lld\n",ans);
    return 0;
}
/*


3 3
3 3
1 3
1 2
*/

 

posted on 2019-09-06 20:40  rua-rua-rua  阅读(192)  评论(0编辑  收藏  举报