zoukankan      html  css  js  c++  java
  • BZOJ3868 : The only survival

    枚举每个点到$1$的距离,若$>k$则视为$k+1$,那么$d_1=1,d_n=k$。

    对于$i$,如果$1leq d_ileq k$,则一定要存在一条边长度为$d_i-d_j$,且其他边长度都要$geq d_i-d_j$。

    如果$d_i>k$,那么对于每条边都满足长度$>k-d_j$。

    枚举每个$d$的个数,通过排列组合进行指派,然后通过DP计算方案数。

    状态为$f[i][j]$表示$x$考虑了$1$到$i$这些点的连边,是否存在一条边使得这个距离合法的方案数。

    时间复杂度$O(nB(n))$。

    #include<cstdio>
    const int N=15,P=1000000007;
    int T,n,k,L,i,j,C[N][N],d[N],now,ret,f[2],ans;
    inline int fix(int x){return x<L?x:L;}
    void dfs(int x,int y,int z,int now){
      if(x==2&&y==0)return;
      d[x]=y;z|=y==k;
      if(x>1)if(y<=k){
        f[0]=1,f[1]=0;
        for(i=1;i<x;i++)if(d[i]==y){
          f[0]=1LL*f[0]*L%P;
          f[1]=1LL*f[1]*L%P;
        }else{
          f[1]=(1LL*f[1]*(L-y+d[i]+1)+f[0])%P;
          f[0]=1LL*f[0]*(L-y+d[i])%P;
        }
        now=1LL*now*f[1]%P;
      }else for(i=1;i<x;i++)now=1LL*now*fix(L-k+d[i])%P;
      if(x==n){
        if(!z)return;
        for(ret=n-2,i=2;i<=n;i=j){
          for(j=i;j<=n&&d[i]==d[j];j++);
          if(d[i]==k)i++;
          now=1LL*now*C[ret][j-i]%P;
          ret-=j-i;
        }
        ans=(ans+now)%P;
        return;
      }
      for(;y<=k+1;y++)dfs(x+1,y,z,now);
    }
    int main(){
      for(C[0][0]=i=1;i<N;i++)for(C[i][0]=j=1;j<=i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
      scanf("%d",&T);
      while(T--){
        scanf("%d%d%d",&n,&k,&L);
        if(n==1||k>L){puts("0");continue;}
        if(n==2){puts("1");continue;}
        dfs(1,ans=0,0,1);
        printf("%d
    ",ans);
      }
      return 0;
    }
    

      

  • 相关阅读:
    程序员开发工作之算法和架构
    iOS开发学习概述及知识整理
    git基本技巧及进阶
    使用命令行工具运行Xcode 7 UI Tests
    技巧集锦2
    Xcode开发小问题集锦
    Xcode 7如何 免费 真机调试iOS应用
    常用shell script 珍藏
    多线程学习7--CountDownLatch
    学习多线程6---栅栏
  • 原文地址:https://www.cnblogs.com/clrs97/p/5690267.html
Copyright © 2011-2022 走看看