[思维][DFS]JZOJ 4807 破解
分析
有个显然的结论,操作完的串必定是000...111...000...111这样的串
那么我们只需要知道01交界的位置即可,因为位置不同,则串必定不同
显然,这个位置一定是区间$[l,r)$的端点,而且操作偶数次时,这个端点必不是关键位置
那我们可以从$l$向$r$连边,这会构成许多联通块,不难想到联通块中的都是关键点,所以一个联通块的方案数为$2^{n-1}$,n为联通块中点的个数
那么有$m$个点,$k$个联通块,答案即为$2^{m-k}$
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; const int N=1e5+10; const int P=1e9+7; struct Graph { int v,nx; }g[2*N]; int cnt,list[100*N]; bool vis[100*N]; int t,n,m,p; void Add(int u,int v) { g[++cnt]=(Graph){v,list[u]};list[u]=cnt; g[++cnt]=(Graph){u,list[v]};list[v]=cnt; } void DFS(int u) { p++;vis[u]=1; for (int i=list[u];i;i=g[i].nx) if (!vis[g[i].v]) DFS(g[i].v); } int Power(int x,int y) { int ans=1; while (y) { if (y&1) ans=1ll*ans*x%P; x=1ll*x*x%P; y>>=1; } return ans; } int main() { for (scanf("%d",&t);t;t--) { int k=0;p=0; scanf("%d%d",&n,&m); cnt=0;memset(list,0,sizeof list);memset(vis,0,sizeof vis); for (int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),Add(u,v+1); for (int i=1;i<=n;i++) if (!vis[i]&&list[i]) DFS(i),k++; printf("%d\n",Power(2,p-k)); } }
在日渐沉没的世界里,我发现了你。