zoukankan      html  css  js  c++  java
  • 【JZOJ4807】破解

    Description

    历经千辛万苦,ddddddpppppp 终于找到了IBN5100。 dp 事先了解到SERN 共有T 个密码,每个密码是一个长度为N 的01 串,他要利用IBN5100 的特殊功能破解SERN 的密码。 初始时,IBN5100 中的串每个位置都是0。 这台特殊的IBN5100 还提供了M 个区间[Li,Ri],每次操作是从给定区间中选 择其中一个区间[Li,Ri],将当前01 串[Li,Ri]的位置上的数字全部取反。 dp 可以执行上述操作任意次。为了破解出密码,dp 想知道这个01 串最多有多 少种可能。 
    由于答案可能很大,所以你只需要告诉 dp 模(10^9+7)后的答案即可。 
    注意:每次破解都是独立的。

    Input

    第一行,一个整数T 表示一共T 组数据。 
    每组数据第一行,两个整数N,M,分别表示密码串长度和区间个数。 
    接下来M 行,第i 行两个整数Li,Ri 表示一个区间[Li,Ri]。

    Output

    每组数据一行,一个整数表示所有的可能,答案对(10^9+7)取模。

    Sample Input


    3 3 
    1 1 
    2 2 
    3 3 
    5 2 
    1 2 
    4 5

    Sample Output


    4

    Hint

    【样例解释】 
    第一组数据:每个位置都可以单个修改,所以所有长度为3 的01 串都有可能,即2^3=8 种可能。 
    第二组数据的四种可能如下: 
    1.不操作:00000 
    2.选择区间[1,2]:11000 
    3.选择区间[4,5]:00011 
    4.先选择区间[1,2]再选择[4,5]:11011

    【数据范围】 
    对于30%的数据,N,M ≤ 10 
    对于60%的数据,N ≤ 10000000 , M ≤ 20 
    对于100%的数据,N ≤ 10000000 , M ≤ 100000 ,1 ≤ Li ≤ Ri ≤ N , T≤ 10

     
    题解:
         这个题目很巧秒,显然如果区间与区间之间没有相互之间影响,那么答案就会是2^n次方,也就是每个区间有乘二的贡献,因为既然你相互不影响,那我这个区间就有反和不反两种情况,但既然会影响所以我们要想办法把本质不同的组合给筛选出来。
      就是一个区间或者一个组合如果能被多个区间或者组合所取代,那么他们的本质就是一样的,所以我们只要乘一次二就可了,怎么筛选,用并查集连边判重就可以了。
     
    代码:
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    #define mod 1000000007;
    const int MAXN=10000010;
    using namespace std;
    int fa[MAXN],l[MAXN],r[MAXN],v[MAXN];
    int n,m,t;
    int num=0;
     
    int find(int x){
        if(fa[x]!=x) fa[x]=find(fa[x]);
        return fa[x];
    }
     
    void cl(){
        memset(fa,0,sizeof(fa));
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
        memset(v,0,sizeof(v));
    }
     
    int main(){
        scanf("%d",&t);
        while(t--){
            cl();
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++){
                scanf("%d%d",&l[i],&r[i]);r[i]++;
            }
            for(int i=1;i<=n+3;i++) fa[i]=i;
            ll ans=1;
            for(int i=1;i<=m;i++){
                int x=find(l[i]),y=find(r[i]);
                if(x==y) continue;
                ans*=2;ans%=mod;
                fa[x]=y;
            }
            printf("%lld
    ",ans);
        }
    }
    …………
  • 相关阅读:
    solr7之solrJ的使用
    solr7.3.1在CentOS7上的安装
    nginx配置:location配置方法及实例详解
    [读书]10g/11g编程艺术深入体现结构学习笔记(持续更新...)
    liunx系统计划任务管理(at/crond调度)
    Golden Gate 概念和机制
    Oracle三大经典表连接适用情况
    Oracle索引简单介绍与示例
    Oracle RAC的日志体系
    Oracle10g RAC的简单操作
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7288081.html
Copyright © 2011-2022 走看看