题目:
暴搜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 ",maxn); exit(0); } if(pos>m){//printf("x:%d ",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 ",ans); return 0; } /* 3 3 1 1 2 2 3 3 */
分析:
如果每一个点都可以翻转的话,就是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 ",cnt); ans=quick_pow(2,cnt); printf("%lld ",ans); return 0; } /* 3 3 3 3 1 3 1 2 */