1 1 1 1 2 1 1 2
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; }