HDU3461_Code Lock

Description

一排可以转动的密码锁,现在给你很多个区间,你可以操作同时转动这个区间内的密码锁,能够通过转动使之一样的密码锁为一种密码

如可以操作2~4这个区间:那么ABBB 和AAAA是一个密码

问你这个密码锁总共有多少种不同的密码

思路:

如果这题没有转动限制的话,那么答案很明显,就是(n为区间大小)26的n次方,但是由于可以转动所以有些锁的状态会重复,那么同一个状态重复了多少次呢!!!!设有cnt个可以自由移动的区间,那么重复次数就是26的cnt次方(想一想为什么,和数学的排列组合很像),那么除以重复次数就可以了

结果是26的(n-cnt)次方种不同的状态锁,显然要用到快速幂

现在最大的问题就是怎么求独立区间个数,


模拟过程:

现在有一个独立区间A[1,4]和B[5,8],现在多出来一个C区间[1,9],显然C任何一种状态都可由转动AB这两个得到,那么C的加入并没有增加新的独立区间,此时C=A+B,同理C=A-B也没有增加新的独立区间

容易发现没有增加新的独立区间的C有一个特点,C区间的两端已经"连在"了一起.

而这种是通过并查集实现的!!!只想说为什么这么神奇!!!!!每次增加一个区间的 时候就把区间左端点和右端点+1联合起来,如果一个新增加的区间左端和右端+1并没有在一个集合,说明这是一个独立区间,否则不是,就这样统计独立区间个数

然后用快速幂就好了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<stack>
#include<map>
#include<queue>
#include<vector>

using namespace std;
const int maxn = 1e7+100;
const int MOD = 1000000007;
#define pr(x) cout << #x << " = " << x << " ";
#define prln(x) cout << #x << " = " << x <<endl;
#define ll long long
int p[maxn];
int findset(int x) {
    return p[x] = x == p[x]? x: findset(p[x]);
}
bool unite(ll x, ll y) {
    x = findset(x), y = findset(y);
    if(x == y) return false;
    p[x] = y;
    return true;
}
ll fun(ll x, ll m) {
    ll ans = 1;
    while(m) {
        if(m & 1) ans = ans * x % MOD;
        x = x * x % MOD;
        m >>= 1;
    }
    return ans % MOD;
}
int main(){
#ifdef LOCAL
    //freopen("C:\\Users\\User Soft\\Desktop\\in.txt","r",stdin);
  //freopen("C:\\Users\\User Soft\\Desktop\\out.txt","w",stdout);
 #endif
    ll m, n, l, r, cnt;
    while( scanf("%lld%lld", &n, & m) == 2) {
        cnt = n;
        for(int i = 0; i <= n; ++i) p[i] = i;
        for(int i = 0; i < m; ++i) {
            scanf("%lld%lld", &l, &r);
            cnt -= unite(l - 1, r);
        }
        cout << (fun(26,cnt)+MOD)%MOD << "\n";
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值