• BZOJ


    题意:

      给定两个序列$a$和$b$,让它们进行匹配,求出使得$a_i > b_j$的个数比$a_i < b_j$的个数恰好多$k$,求这样的匹配方法数

    题解:

      这题的各种表示有一点相似又截然不同,很容易混淆。

      直接求恰好满足$k$对不好求,所以先放宽条件,这样子有利于构造动规方程。

      先用$f_{i, j}$表示在前$i$个中,至少选择$j$个$a > b$的匹配的方案数(是匹配的方案数,只关心匹配那一部分,不关心其它的部分),容易得到动规方程:

                         ƒi,jƒi - 1,j + (Lasti - (j - 1)) * ƒi - 1,j - 1

      其中$Last_i$表示第一个小于$a_i$的$b_j$。

      $(Last_i - (j - 1))$表示原有$Last_i$种选择,被选走了$j - 1$种,此时因为是“至少”,所以其它的匹配是不用管的。

      那么现在考虑求出恰好为$k$的方案数。

      首先令$g_i$表示前$N$个$a$中,满足至少有$i$个$a > b$的方案数,那么

                          giƒN,j * (N - i) !

      这时候才考虑了其它的部分,所以需要乘上阶乘。

      再令$f'_i$表示恰好满足$i$组的方案数,那么考虑容斥,在所有的$g_j$中,每个$f'_i (i > j)$被算了$C_i^j$次,因为不考虑其它的,仅$i$个已匹配好的任意取$j$个,其它的随便排,正好被$g_j$囊括,当然这一部分是多余的,所以

                          ƒ'i = gj - Cj, i * ƒ'j (j > i)

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 
     6 #define MOD 1000000009
     7 
     8 using namespace std;
     9 
    10 typedef long long LL;
    11 
    12 const int MAXN = 2000 + 10;
    13 
    14 LL g[MAXN][MAXN];
    15 
    16 LL f[MAXN]= {0};
    17 
    18 LL fac[MAXN];
    19 LL C[MAXN][MAXN];
    20 
    21 int N, K;
    22 
    23 int Candy[MAXN], Pill[MAXN];
    24 
    25 int Last[MAXN]= {0};
    26 
    27 void Preparation () {
    28     fac[0] = 1;
    29     for (int i = 1; i <= N; i ++)
    30         fac[i] = fac[i - 1] * i % MOD;
    31     
    32     for (int i = 0; i <= N; i ++)
    33         C[i][0] = 1;
    34     for (int i = 1; i <= N; i ++)
    35         for (int j = 1; j <= i; j ++)
    36             C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
    37 }
    38 
    39 int main () {
    40     scanf ("%d%d", & N, & K);
    41     
    42     Preparation ();
    43     
    44     for (int i = 1; i <= N; i ++)
    45         scanf ("%d", & Candy[i]);
    46     for (int i = 1; i <= N; i ++)
    47         scanf ("%d", & Pill[i]);
    48     
    49     sort (Candy + 1, Candy + N + 1);
    50     sort (Pill + 1, Pill + N + 1);
    51     
    52     for (int i = 1; i <= N; i ++)
    53         for (int j = N; j >= 1; j --)
    54             if (Pill[j] < Candy[i]) {
    55                 Last[i] = j;
    56                 break;
    57             }
    58     
    59     for (int i = 0; i <= N; i ++)
    60         g[i][0] = 1;
    61     for (int i = 1; i <= N; i ++)
    62         for (int j = 1; j <= i; j ++)
    63             g[i][j] = (g[i - 1][j] + (Last[i] - j + 1) * g[i - 1][j - 1] % MOD) % MOD;
    64     
    65     for (int i = N; i >= 1; i --) {
    66         f[i] = g[N][i] * fac[N - i] % MOD;
    67         for (int j = i + 1; j <= N; j ++)
    68             f[i] = ((f[i] - C[j][i] * f[j] % MOD) % MOD + MOD) % MOD;
    69     }
    70     
    71     printf ("%lld
    ", f[(N + K) >> 1]);
    72     
    73     return 0;
    74 }
    75 
    76 /*
    77 4 2
    78 5 35 15 45
    79 40 20 10 30
    80 */
    View Code
  • 相关阅读:
    JavaScript的正则表达式的基础
    运用JS判断代码可以参考学习
    调用百度地图代码
    运用了css,js
    中国地图(Highmaps)
    Centos
    代理模式【 动态代理与静态代理】
    java集合 collection-list-LinkedList 模拟一个堆栈或者队列数据结构。
    java集合 collection-list-LinkedList
    java集合 collection-list-vector
  • 原文地址:https://www.cnblogs.com/Colythme/p/9697675.html
Copyright © 2020-2023  润新知