题目链接
翻译的有点不准确,还是靠自我的理解吧,呐,具体是这样的:第一行 N, M, 接下来有M行,N代表有几个字母组成, M代表有多少个可操作区间。
然后讲一下几个测试样例:
样例一:
表示只有一个字母,这个字母可以是a.....z, 1代表下面只有一个操作区间,就是1 1,
当这个字母是a时, 它经过1 1这个操作区间进行有限次的“增加”后,可以变成b,c,d....z,那么a和b,....z就是同一种锁,
当这个字母是b时, 它经过1 1这个操作区间进行有限次的“增加”后,可以变成a, c,d....z,因为a,....z已经是同一种锁了,,如果这个字母是c....,后面就是一样的,永远是这26个字母,说明是唯一的解:ans==1。
样例二:
2 1 1 2
意思是有两个字母,以及一次操作,为1~2:当这两个字母是ab,在可操作区间1 2,它可以变成bc,cd,.....za;那么ab和bc,cd,.....za就是同种锁;当这两个字母是bc时, 当这两个字母是cd时......等等,这都和当字母是ab时相同,这算一种锁;当字母是ac时,字母ac 和 bd.......zb都是属于同种锁;发现,后面的可能只会随着首字与第二字符的大小来产生个数,第二字符与第一字符的差距可以为0~25,%26只有这26种可能。ans==26。
那么这该如何解呢?尤其是第一个样例还有1~1这样的区间,我们该如何求解?譬如待查询区间为L~R,那么,我们把他们化为L~R+1也没多少区别?为什么这么说呢?我们该如何求解这到底有多少种方案数,如果有一组相互对应,那么26的N次方就会少一组,这个可以自推。然后,为了避免重复,我们将原区间看作L~R+1来处理。
我在这题中还用了离散化的思想(题看错了,数据看大了),不过可以看下,就当练习自己离散化能力了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
const int mod=1e9+7;
const int maxN=1005;
typedef long long ll;
int N, M, m, a[maxN<<1], root[maxN<<1], diff, num[maxN<<1], cnt;
bool cmp(int e1, int e2) { return e1<e2; }
map<int, int> mp;
void init()
{
cnt=0;
mp.clear();
for(int i=1; i<=m; i++) { root[i]=i; }
}
ll fast_mi(ll x, int y)
{
ll ans=1;
while(y)
{
if(y&1) ans = (ans*x)%mod;
x = (x * x)%mod;
y>>=1;
}
return ans;
}
struct Eddge
{
int no, to;
Eddge(int a=0, int b=0):no(a), to(b) {}
}edge[maxN];
int fid(int x) { return x==root[x]?x:(root[x]=fid(root[x])); }
void mix(int x, int y)
{
int u=fid(x), v=fid(y);
if(u != v)
{
root[u] = v;
cnt++;
}
}
int main()
{
while(scanf("%d%d", &N, &M)!=EOF)
{
m = 2*M;
for(int i=1; i<=M; i++)
{
scanf("%d%d", &edge[i].no, &edge[i].to);
a[2*i-1] = edge[i].no;
a[2*i] = edge[i].to + 1;
}
init();
sort(a+1, a+1+m, cmp);
diff = (int)(unique(a+1, a+1+m) - a - 1);
//printf("diff: %d\n", diff);
for(int i=1; i<=diff; i++)
{
mp[a[i]]=i;
//printf("%d\n", a[i]);
}
for(int i=1; i<=M; i++)
{
mix(mp[edge[i].no], mp[edge[i].to+1]);
}
printf("%lld\n", fast_mi(26, N-cnt)%mod);
}
return 0;
}