hdu3461Code 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 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

这个题在早上看一遍,题意又没懂 简单看了下题意解释:点击打开链接

晚上还是稀里糊涂 自己推导非得觉得是把字符串的哈希之类的连在一起 (⊙﹏⊙)b 能做出来才怪 不过发现了 26^N的惊天奥义 然并卵 并没有发现26^(N-x)这个梗

还是没彻底理解好题目的意思 →_→ 他说 给定一个区间 把这个区间的所有字母都加一 变换出来的字符串与原来的算作一个 不要纠结于怎么选择初始的字符串 反正++的转一圈走过的肯定是26个!所以 很好理解的是 每出现一个集合 最终的组合数就少到26分之一

好吧 我想到这么大数 就想到快速幂了 然而没敢继续往下想  23333 人间悲剧

还是跟并查集有关系的 你想啊 一个集合少26倍 怎么算作一个集合呢?看看 并查集来了吧

【1,3】+【4,5】==【1,5】 然而【1,3】+【3,5】!=【5,5】前者的关系就需要并查集来处理啊:小区间合并成大区间 而后者不能作为一个大集合出现 

#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 10000005
#define mod 1000000007
int f[maxn],n,m,l,r,count;
bool vis[maxn];
int find(int x)
{
    if(x!=f[x]) f[x]=find(f[x]);
    return f[x];
}
void addto(int x,int y)
{
    x=find(x),y=find(y);
    if(x==y) return ;
    f[x]=y;
    count++;
}
long long multi(int x)
{
    long long ans=1,tmp=26;
    while(x)
    {
        if(x&1) ans=(ans*tmp)%mod;
        tmp=(tmp*tmp)%mod;
        x>>=1;
    }
    return ans;
}
int main()
{
   // freopen("cin.txt","r",stdin);
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n+1;i++) f[i]=i;
        count=0;
        while(m--)
        {
            scanf("%d%d",&l,&r);
            addto(l,r+1);
            vis[l]=1,vis[r+1]=1;
        }
        /*for(int i=1;i<=n+1;i++)
        {
            if(vis[i]&&f[i]==i) count++;
        }*/
        printf("%lld\n",multi(n-count)%mod);
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值