zoukankan      html  css  js  c++  java
  • hdu 5852 :Intersection is not allowed! 行列式

    有K个棋子在一个大小为N×N的棋盘。一开始,它们都在棋盘的顶端,它们起始的位置是 (1,a1),(1,a2),...,(1,ak) ,它们的目的地是 (n,b1),(n,b2),...,(n,bk)。

    一个位于 (r,c) 的棋子每一步只能向右走到 (r,c+1) 或者向下走到 (r+1,c) 。

    我们把 i 棋子从 (1,ai) 走到 (n,bi) 的路径记作 pi 。

    你的任务是计算有多少种方案把n个棋子送到目的地,并且对于任意两个不同的棋子 i,j ,使得路径 pi 与 pj 不相交(即没有公共点)。

    容斥原理。

    假设只有两个点,那么答案就是它们以任意路径到达终点的方案数减去相交的方案。

    比如 a1->b1 ,a2->b2 ,那它们相交的方案就是 a1->b2,a2->b1的所有方案。

    因为在最后一个交点下把两条路径换一下它们是一一对应的。

    扩展到多个点时有$n!$种向下对应对应的方案,每个方案的容斥系数是$-1^{逆序对个数}$。

    实际上这东西就是矩阵的行列式。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define ll long long
     6 #define N 105
     7 using namespace std;
     8 int n,k;
     9 const int inf = 200000;
    10 const int p = 1000000007;
    11 int jie[200005],ni[200005];
    12 void yu()
    13 {
    14     jie[0]=ni[0]=ni[1]=1;
    15     for(int i=1;i<=inf;i++)jie[i]=1LL*i*jie[i-1]%p;
    16     for(int i=2;i<=inf;i++)ni[i]=(1LL*(-p/i)*ni[p%i]%p+p)%p;
    17     for(int i=1;i<=inf;i++)ni[i]=1LL*ni[i-1]*ni[i]%p;
    18 }
    19 int pw(ll x,int y)
    20 {
    21     ll lst=1;
    22     while(y)
    23     {
    24         if(y&1)lst=lst*x%p;
    25         y>>=1;
    26         x=1LL*x*x%p;
    27     }
    28     return (int)lst;
    29 }
    30 int c(int n,int m)
    31 {
    32     return 1LL*jie[n]*ni[m]%p*ni[n-m]%p;
    33 }
    34 int st[N],ed[N];
    35 ll a[N][N];
    36 void guess()
    37 {
    38     ll ans=1;
    39     for(int i=1;i<=k;i++)
    40     {
    41         for(int j=i;j<=k;j++)
    42         {
    43             if(a[j][i])
    44             {
    45                 if(j!=i)ans*=-1;
    46                 for(int l=1;l<=k;l++)swap(a[i][l],a[j][l]);
    47                 break;
    48             }
    49         }
    50         ll tp=pw(a[i][i],p-2);
    51         for(int j=i+1;j<=k;j++)
    52         {
    53             if(a[j][i])
    54             {
    55                 ll tmp=p-tp*a[j][i]%p;
    56                 for(int l=i;l<=k;l++)
    57                 {
    58                     a[j][l]=(a[j][l]+tmp*a[i][l]%p)%p;
    59                 }
    60             }
    61         }
    62     }
    63     if(ans==-1)ans=p-1;
    64     for(int i=1;i<=k;i++)ans=ans*a[i][i]%p;
    65     printf("%lld
    ",ans);
    66     return ;
    67 }
    68 int main()
    69 {
    70     yu();
    71     scanf("%d%d",&n,&k);
    72     for(int i=1;i<=k;i++)scanf("%d",&st[i]);
    73     for(int i=1;i<=k;i++)scanf("%d",&ed[i]);
    74     for(int i=1;i<=k;i++)
    75     {
    76         for(int j=1;j<=k;j++)
    77         {
    78             if(ed[j]>=st[i])a[i][j]=c(n-1+abs(ed[j]-st[i]),n-1);
    79         }
    80     }
    81     guess();
    82     return 0;
    83 }
  • 相关阅读:
    poj 3243 Clever Y(BabyStep GiantStep)
    poj 2417 Discrete Logging
    poj 3481 Double Queue
    hdu 4046 Panda
    hdu 2896 病毒侵袭
    poj 1442 Black Box
    hdu 2815 Mod Tree
    hdu 3065 病毒侵袭持续中
    hdu 1576 A/B
    所有控件
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6670187.html
Copyright © 2011-2022 走看看