HDU - 3461 Code Lock(并查集+快速幂)

点击打开题目链接

Code Lock

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 2043    Accepted Submission(s): 788

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 changes to the next letter in the English alphabet (if it was showing the last letter 'z', then it changes to 'a').
At each operation, you are only allowed to move some specific subsequence of contiguous wheels up. This has the same effect of moving each of the wheels up within the subsequence.
If a lock can change to another after a sequence of operations, we regard them as same lock. Find out how many different locks exist?

Input

There are several test cases in the input.

Each test case begin with two integers N (1<=N<=10000000) and M (0<=M<=1000) indicating the length of the code system and the number of legal operations. 
Then M lines follows. Each line contains two integer L and R (1<=L<=R<=N), means an interval [L, R], each time you can choose one interval, move all of the wheels in this interval up.

The input terminates by end of file marker.

Output

For each test case, output the answer mod 1000000007

Sample Input

 
 
1 1 1 1 2 1 1 2

Sample Output

 
 
1 26

Author

hanshuai

Source

Recommend

zhouzeyong   |   We have carefully selected several similar problems for you:   3465  3467  3468  3464  3462 

Statistic | Submit | Discuss | Note

弱鸡的我很难想到并查集做。(QAQ)

题目大意:一个N长度的字母密码锁,可以任意改变任一字母的值。现在给定M个区间,每次改变,区间内的字母都改变,如果密码锁转动之后结果一样,就看做同一种密码锁,问有多少种不同的密码锁。例如一种密码锁为【abcde】,区间为【1,2】,改变一次则变为【bccde】。

思路:①如果不存在区间,则共有26^N个密码锁。

  ②如果有一个区间且长度为1,例如【abcde】,区间【1,1】,则第一个字母a可以取任意字母,如果任意锁与该锁后四个字母相同,即相同锁。所以此时共有26^(N-1)个密码锁。

  ③如果有一个区间长度任意,例如【abcde】,区间【1,3】如果任意锁与该锁后四个字母相同,并且前三个字母ASCII值相对位置相同,即相同锁。所以此时共有26^(N-3)个密码锁。

  ④对于普通情况,共n个区间,每个区间长度任意,共有26^(N-n)个密码锁。

现在问题出来了,例如【abcde】,区间【1,2】,【3,5】,【1,5】。改变前两个区间和改变第三个区间操作结果是一样的,此时有两种密码锁。

但是对于【1.2】,【2,5】【1,5】则不同,因为2操作重复了一次,此时有三种密码锁。所以合并的时候用(a-1,b)即可)(所以最初初始化从0开始)

这个时候就可以想到并查集了,统计共有sum个联动独立的区间,然后最后得到26^(N-sum)取模运算即可

WA了一次,因为快速幂应该用long long.

附上AC代码:

#include<iostream>

using namespace std;
typedef long long ll;
const int maxn=10000000+5;
const int mod=1000000007;
int par[maxn];
int sum;
int N,M,L,R;

void init()
{
    for(int i=0;i<maxn;i++)
        par[i]=i;
        sum=0;
}

int find(int a)
{
    if(a==par[a])return a;
    return par[a]=find(par[a]);
}

void unite(int a,int b)
{
    a=find(a);
    b=find(b);
    if(a==b)return ;
    else if(a!=b)
    {
        sum++;
        if(a>b)par[a]=b;
        else par[b]=a;
    }
}

ll pow_mod(ll a,ll b,int n)
{
    if(b==0)return 1;
    ll x=pow_mod(a,b/2,n);
    ll ans=x*x%n;
    if(b%2)ans=ans*a%n;
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    while(cin>>N>>M)
    {
        init();
        for(int i=0;i<M;i++)
        {
            cin>>L>>R;
            unite(L-1,R);
        }
        cout<<pow_mod(26,N-sum,mod)%mod<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chook_lxk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值