zoukankan      html  css  js  c++  java
  • [NOIP2019模拟赛]HC1147 时空阵

    题目描述:

    幽香这几天学习了魔法,准备建造一个大型的时空传送阵。

    幽香现在可以在幻想乡的n个地点建造一些传送门,如果她建造了从地点a与地点b之间的传送门,那么从a到b和从b到a都只需要单位1的时间。

    同时这些地点之间在地理上是非常遥远的,因此来往他们必须使用传送门。

    现在幽香想要问你,有多少种建造传送门的方案,使得地点1和地点n之间的最短距离恰好为k?两个方案不同当且仅当建造的传送门的集合不同。不能建造节点到自身的传送门,两个点之间也最多造一个传送门。

    分析:

      DP...

      然而考场上没时间了,只打了20pts(k==1)

      为了防止变量名冲突,题面中的k在代码中都用m代替!!!

      首先:显然这道题的合法路径是一层一层的节点组成的

      然后就可以DP了(话说考场上状态设计都设计出来了,转移没时间了...)

      设f[i][j][k]表示当前进行到第i层,总共使用了j个节点,第i层使用了k个节点

      显然这个可以有f[i-1][j-k][s]转移过来,我们只要枚举s就可以了,现在我们只要计算f[i-1][j-k][s]的系数就好了

      分类讨论:

        当i<m时:

          ①可以当前层内部连边,也就是$2^{C_k^2}$种可能

          ②当前层与上一层连边,且当前层的所有点至少有一条边连出去,也就是$(sumlimits_{p=1}^{s}C_s^p-1)^k$

            tip:上式子用二项式定理可以化简为$(2^{s}-1)^k$

          ③注意到当前这k个点是从剩下的n-j+k-1(最后减一是因为第n个点必须放在第m层)所以从这里面选k个点,方案数为$C_{n-j+k-1}^k$

        综上:$$f[i][j][s]=sum f[i-1][j-k][s]*(2^s-1)^k*C_{n-j+k-1}^k*C_k^2$$

        当i==m时

          注意到只有第③个条件需要改变,也就是说第n个点肯定在这一层,所以只要在n-j+k-1中选择k-1的点即可,方案数为$C_{n-j+k-1}^{k-1}$

        即:$$f[i][j][s]=sum f[i-1][j-k][s]*(2^s-1)^k*C_{n-j+k-1}^{k-1}*C_k^2$$

      预处理一下组合数,及时取模,结合快速幂就好了

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 using namespace std;
     4 inline int read(){
     5     int ans=0,f=1;char chr=getchar();
     6     while(!isdigit(chr)){if(chr=='-')f=-1;chr=getchar();}
     7     while(isdigit(chr)) {ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
     8     return ans*f;
     9 }const int P = 1e9+7;
    10 int n,m,f[105][105][105],ans,cc[105][105];
    11 int ksm(int x,int p){
    12     int ans=1;
    13     for(;p;p>>=1,x=x*x%P) if(p&1) ans=ans*x%P;
    14     return ans;
    15 }
    16 int C(int x,int y){
    17     int mul=1;
    18     for(int i=2;i<=y;i++) mul=mul*i%P;
    19     for(int i=2;i<=x-y;i++) mul=mul*i%P;
    20     int t=ksm(mul,P-2);
    21     mul=1;
    22     for(int i=2;i<=x;i++) mul=mul*i%P;
    23     mul=mul*t%P;
    24 }
    25 inline void Add(int &x,int y){x=x+y;if(x>=P)x-=P;}
    26 inline void Solve(){
    27     f[0][1][1]=1;
    28     for(int i=1;i<=m;++i)
    29         for(int j=1;j<=n;++j)
    30             for(int k=1;k<=j;k++){
    31                 for(int s=1;s<=j-k;s++)
    32                     if(i<m)//第一种 
    33                         Add(f[i][j][k],f[i-1][j-k][s]*ksm(2,(k-1)*k/2)%P*cc[n-j+k-1][k]%P*ksm(ksm(2,s)-1,k)%P);
    34                     else//第二种 
    35                         Add(f[i][j][k],f[i-1][j-k][s]*ksm(2,(k-1)*k/2)%P*cc[n-j+k-1][k-1]%P*ksm(ksm(2,s)-1,k)%P);
    36             }
    37     for(int i=m+1;i<=n;i++)
    38         for(int j=1;j<=n;j++)
    39             Add(ans,f[m][i][j]*ksm(2,(n-i)*(n-i-1)/2+j*(n-i)%P)%P);
    40     cout<<ans<<endl;
    41 }
    42 signed main(){
    43     freopen("timegate.in","r",stdin);
    44     freopen("timegate.out","w",stdout);
    45     for(int i=0;i<=100;i++)for(int j=0;j<=i;j++)cc[i][j]=C(i,j);//预处理组合数 
    46     n=read(),m=read();
    47     Solve();
    48     return 0;
    49 }
  • 相关阅读:
    针对web高并发量的处理
    外边距合并,外边距折叠
    cookie 和session 的区别:
    ng-if ng-show ng-hide 的区别
    JavaScript中的arguments,callee,caller
    git常见命令
    jQuery中.bind() .live() .delegate() .on()的区别
    为什么要使用sass
    js兼容性记录
    poj1004
  • 原文地址:https://www.cnblogs.com/zhenglw/p/11342514.html
Copyright © 2011-2022 走看看