题目拼错系列
我™要是再写这种题我就是狗!!!!!
md调了一天真是智障
首先问题分析一下转化为求哈密尔顿路的个数
基于连通性的状态压缩DP,基于连通性……
但是不能用括号序列表示,所以要用最小表示法
所以大概就是和NOI07的生成树计数差不多吧(我那题代码也写得很挫)
然后大概就是每个点4位,前两位表示所在连通块的标号,后两位表示度数
然后瞎JB搞一下就好了
md连通块合并完了没标号调了一天真是醉了
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int p=(1e9)+7; #define rep(i,l,r) for(int i=l;i<=r;i++) #define tra(i,u) for(int i=head[u];i;i=e[i].next) #define mmt(a,v) memset(a,v,sizeof(a)) int n,k; int get(int s,int i){return ((s>>i)&3)<<i;} int pa(int s,int i){return (s>>((i-1)<<2))&3;} int deg(int s,int i){return ((s>>((i-1)<<2))>>2)&3;} int pro(int i,int p,int d){return (p<<((i-1)<<2))|((d<<((i-1)<<2))<<2);} int adddeg(int s,int i){return s+((1<<(i<<2))>>2);} int modifypa(int s,int i,int p){return (s^get(s,(i-1)<<2))|(p<<((i-1)<<2));} int f[2][70000]; struct Edge{int to,next;}e[100000]; int head[70000],cnt; void ins(int u,int v){e[++cnt]=(Edge){v,head[u]};head[u]=cnt;} int state[70000],tot; int size(int u){ int ans=0; rep(i,1,k)ans=max(ans,pa(u,i)); return ans; } int size(int u,int i){ int ans=0; rep(j,1,k)ans+=pa(u,j)==i; return ans; } void print(int s){ rep(i,1,k)printf("%d %d\n",pa(s,i),deg(s,i)); } void debug(int s){ puts("!");print(s);puts("~"); } int dfs(int i,int sc,int s){ if(i>k)state[++tot]=s; else{ rep(j,0,sc)rep(d,0,2) dfs(i+1,sc,s|pro(i,j,d)); sc++; rep(d,0,2) dfs(i+1,sc,s|pro(i,sc,d)); } } int merge(int s,int a,int b){ if(a>b)swap(a,b); rep(i,1,k)if(pa(s,i)==b)s=modifypa(s,i,a); return s; } int remark(int s){ static bool use[5];mmt(use,0); static int ans;ans=s; static int sc;sc=0; rep(i,1,k){ if(use[i])continue; rep(j,i,k) if(pa(s,i)==pa(s,j)){ use[j]=true; ans=modifypa(ans,j,sc); } sc++; } return ans; } void debug(int u,int v){ puts("~");print(u);print(v);puts("~"); } void find(int u){ static int lim,v,w,t; lim=size(u,0)==1?1:k; rep(i,1,lim){ if(deg(u,i)==2)continue; v=adddeg(u,i); if(lim==1){ rep(j,2,k)v=modifypa(v,j,pa(v,j)-1); v=(v>>4)|pro(k,size(u),1); }else{ v=(v>>4)|pro(k,pa(u,i),1); } v=remark(v); ins(u,v);t=pa(v,k); rep(j,i+1,k){ if(deg(u,j)==2||t==pa(v,j-1))continue; w=adddeg(v,j-1); w=adddeg(w,k); w=merge(w,t,pa(v,j-1));w=remark(w); ins(u,w); } } if(lim!=1){ v=(u>>4)|pro(k,size(u)+1,0); v=remark(v); ins(u,v); } } int now,last; void boom(int i,int sc,int s){ if(i>k)f[now][s]++; else{ rep(j,1,i-1)if(deg(s,j)!=2){ static int u;u=adddeg(s,j); boom(i+1,size(u),u|pro(i,pa(s,j),1)); rep(t,j+1,i-1)if(deg(u,t)!=2){ if(pa(s,j)==pa(s,t))continue; static int v;v=adddeg(u,t); v=merge(v,pa(v,j),pa(v,t)); v|=pro(i,pa(v,j),2);v=remark(v); boom(i+1,size(v),v); } } sc++; boom(i+1,sc,s|pro(i,sc,0)); } } int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); while(~scanf("%d%d",&n,&k)){ if(n==1){puts("1");continue;} if(!k){puts("0");continue;} tot=0;dfs(1,-1,0); now=0;last=1; mmt(head,0);cnt=0; rep(i,1,tot)find(state[i]); mmt(f[now],0); boom(1,-1,0); rep(node,k+1,n){ now^=1;last^=1; mmt(f[now],0); rep(j,1,tot){ int u=state[j]; if(!f[last][u])continue; int count=0; tra(i,u){ int v=e[i].to; (f[now][v]+=f[last][u])%=p; } } } int ans=0; rep(i,1,tot)if(size(state[i])==0&&f[now][state[i]]) (ans+=f[now][state[i]])%=p; printf("%d\n",ans*2%p); } return 0; }