hdu Code Lock

题意是说有N个字母组成的密码锁, 如【wersdfj】,   每一位上的字母可以转动, w可转动变成x, z变成a。但是题目规定, 只能同时转动某个区间上的所有字母, 如【1,3】, 那么第1到第3个的所有字母要同时转动,那么【 wersdfj 】经过一次操作就变成 【 xfssdfj 】.    一共有M 个区间是可以操作的。

题目还规定:If a lock can change to another after a sequence of operations, we regard them as same lock.

就是说, 经过可操作区间进行的操作得到的所有锁情况,都是同一个的。 也就是说,所有不同的锁就是“不可操作区间”的所有组合情况。

这题其实就是并查集+二分求幂。首先要求出可以活动的区间数x,一个区间等价于某一位的密码种类为1,那么得到的密码锁的种类为26^(n-x),因为n的数据较大,所以要用到二分求幂的方法。

先来分析一下二分求幂:

递归算法:

double powerWithUnsignedExponent(double base,unsigned int exponent)
{
    if(exponent==0)
        return 1;
    if(exponent==1)
        return base;
    double result=powerWithUnsignedExponent(base,exponent>>1);//exponent>>1即exponent/2
    result*=result;
    if(exponent & 0x1==1)//a & 0x1相当于a%2
        result*=base;
    return result;
}  

非递归算法:

int power(int a,int b)
{
    int ans=1;
    while(b!=0)
    {
        if(b%2==1)
            ans*=a;
        b/=2;
        a*=a;
    }
    return ans;
}  

再来分析一下这道题的区间判定问题,这题给出的区间可能会存在重叠的情况。例如[1,4]、[4,6]和[1,6],这个应该算3个区间,因为第三个区间不能由前两个区间组合得到。二

[1,4]、[5,6]和[1,6]却只能算两个区间,因为最后一个区间的所有情况可以由前两个区间得到。

所以这题的思路就是:

1、求出所有的区间个数,注意区间重复和重叠的情况,这里用了一个很巧妙的方法,可以把原来的区间左边界减一,这样就可以很简单的避免上面的问题了。

2、用二分幂的方法求出最终的结果。

这里注意int还是不够用的,要用64位整型:

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"string"
#include"string.h"
#include"cmath"
#include"queue"
#include"stack"
#include"vector"
using namespace std;
const int mx=10000001;
const int inf=1000000007;
int fa[mx];
int cnt;
int n,m;

void Set()
{
   int i;
   for(i=0;i<=n;++i)
        fa[i]=i;
}

int Find(int x)
{
    int t1,t2=x;
    while(t2!=fa[t2]) t2=fa[t2];
    while(x!=t2)
    {
        t1=fa[x];
        fa[x]=t2;
        x=t1;
    }
    return t2;
}

bool Union(int x,int y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx==fy)
        return false;
    else
    {
        fa[fx]=fy;
        return true;
    }
}
long long binary_power(int N)
{
    long long base=26,res=1;
    while(N)
    {
        if(N&1)
        {
            res=(res*base)%inf;
        }
        N/=2;
        base=(base*base)%inf;
    }
    return res;
}
void IO()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        int i,l,r;
        cnt=0;
        Set();
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&l,&r);
            l--;
            if(Union(l,r)) cnt++;
        }
        printf("%lld\n",binary_power(n-cnt)%inf);
    }
}
int main()
{
//    freopen("E:\\in.txt","r",stdin);
    IO();
    return 0;
}

时间: 2024-10-10 10:01:05

hdu Code Lock的相关文章

HDU 2017 Code Lock (并查集的应用+快速幂)

链接:HDU 3461 题目大意: 题目的大意是一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限次的"增加"操作后可以变成另一组密码,那么我们认为这两组密码是相同的.该题的目标就是在给定N.M和M个区间的前提下计算有多少种不同的密码. 根据题意,如果一个可调整的区间都没有的话,答案应该是26

HDU 3461 Code Lock(并查集的应用+快速幂)

* 65536kb,只能开到1.76*10^7大小的数组.而题目的N取到了10^7,我开始做的时候没注意,用了按秩合并,uset+rank达到了2*10^7所以MLE,所以貌似不能用按秩合并. 其实路径压缩也可以不用.............  题目的大意: 一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限

Code Lock

Code Lock Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 255 Accepted Submission(s): 114   Problem Description A lock you use has a code system to be opened instead of a key. The lock contains a

HDU 3461 Code Lock(并查集+二分求幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3461 A lock you use has a code system to be opened instead of a key. The lock contains a sequence of wheels. Each wheel has the 26 letters of the English alphabet 'a' through 'z', in order. If you move a

HDU 3461 - Code Lock

Problem Description A lock you use has a code system to be opened instead of a key. The lock contains a sequence of wheels. Each wheel has the 26 letters of the English alphabet 'a' through 'z', in order. If you move a wheel up, the letter it shows c

Code Lock HDU 3461

给定由N个字母组成的密码锁,如[abcdef]每一位字母都可以转动,转动该字母时,将变成它的下一个字母,如'a'转动后是b,x转动后是y, 接着给定M个区间,每次转动给定区间内的所有字母,如密码锁[abcdef],给定区间[1,3]转动这个区间一次后变为[bcddef]; 题解:  要是用并查集蒙的话,有可能就很容易的蒙出来了,但是要是证明的话还是有点难度的.... 待续: Problem Description A lock you use has a code system to be op

hdu 3461 Code Lock(并查集)

想不到这还可以用并查集解,不过后来证明确实可以…… 题意也有些难理解—— 给你一个锁,这个所由n个字母组成,然后这个锁有m个区间,每次可以对一个区间进行操作,并且区间中的所有字母要同时操作.每次操作可以将区间中所有字母+1.即把a变成b,把z变成a. 举个例子,比如有一个锁,由abcdef组成,前三个字母abc是一个区间,第四五个字母de是一个区间,那么如果对abc操作一次,则获得新锁bcddef,再对de区间操作一次,得bcdeff.但是,最后一个字母f是不能操作的. 如果一把锁通过对可操作区

hdu3461 Code Lock

Problem Description A lock you use has a code system to be opened instead of a key. The lock contains a sequence of wheels. Each wheel has the 26 letters of the English alphabet 'a' through 'z', in order. If you move a wheel up, the letter it shows c

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i