• [BZOJ 3622]已经没有什么好害怕的了


    世萌萌王都拿到了,已经没有什么好害怕的了——    (作死)

    笑看哪里都有学姐,真是不知说什么好喵~

    话说此题是不是输 0 能骗不少分啊,不然若学姐赢了,那么有头的学姐还能叫学姐吗?  (作大死)

    这题的数据就告诉我们这是赤裸裸的 dp ,不过要加个容斥而已

    注意到我们可以算出一共需要 s 组满足糖果数 > 药片数

    (在这里显然有个特判,即 n-k 为奇数时,答案一定为 0 )

    我们将两个读入的数组排序

    令 next[i] 表示最大的 j 满足 糖果[i]>药片[j]

    令 f[i][j] 表示枚举到第 i 个糖果时,有 j 组糖果数 > 药片数,但剩下的情况是不考虑的

    则 f[i][j]=f[i-1][j]+f[i-1][j-1]*(next[i]-j+1)

    但若把 f[n][s] 直接输出是妥妥地 WA 因为会有这种情况出现:

    糖果: a1,a2,a3

    药片: b1,b2,b3

    a1>b1  a2>b2  a3>b3

    那么 ((a1,b1),(a2,b2),a3不明)  ((a1,b1),(a3,b3),a2不明) 就会被视为两种答案

    可见我们要求出的是 f’[n][s] 表示 n 个糖果,有 s 组糖果数 > 药片数,剩下的都是药片数 > 糖果数

    这里就要用容斥了


    这个挺好理解的吧

    (n-i)! 是枚举后面 n-i 可能的方案,f‘[n][j]*C(j, i) 表示 f[n][i] 中实际有 j 组药片数 > 糖果数却被计入 f[n][i] 的数量

    f'[n][s]就是答案了,总时间复杂度为 O(n2)

     1 #include <cstdio>
     2 #include <algorithm>
     3 const int mod=1000000009;
     4 const int size=2048;
     5 
     6 namespace IOspace
     7 {
     8     inline int getint()
     9     {
    10         register int num=0;
    11         register char ch;
    12         do ch=getchar(); while (ch<'0' || ch>'9');
    13         do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
    14         return num;
    15     }
    16     inline void putint(int num, char ch='
    ')
    17     {
    18         char stack[15];
    19         register int top=0;
    20         if (num==0) stack[top=1]='0';
    21         for ( ;num;num/=10) stack[++top]=num%10+'0';
    22         for ( ;top;top--) putchar(stack[top]);
    23         if (ch) putchar(ch);
    24     }    
    25 }
    26 
    27 int n, k;
    28 int a[size], b[size];
    29 int next[size];
    30 int fact[size];
    31 int C[size][size];
    32 int f[size][size];
    33 inline int add(int x, int y) {return (x+y)%mod;}
    34 inline int sub(int x, int y) {return (x-y+mod)%mod;}
    35 inline int mul(int x, int y) {return static_cast<long long>(x)*y%mod;}
    36 inline void prepare();
    37 
    38 int main()
    39 {
    40     n=IOspace::getint(), k=IOspace::getint();
    41     if ((n-k)&1) {putchar('0'); putchar('
    '); return 0;}
    42     k=(n+k)>>1;
    43     for (int i=1;i<=n;i++) a[i]=IOspace::getint();
    44     for (int i=1;i<=n;i++) b[i]=IOspace::getint();
    45 
    46     prepare();
    47 
    48     f[0][0]=1;
    49     for (int i=1;i<=n;i++)
    50         for (int j=0;j<=i;j++)
    51         {
    52             f[i][j]=f[i-1][j];
    53             if (j && next[i]-j+1>0)
    54                 f[i][j]=add(f[i][j], mul(f[i-1][j-1], next[i]-j+1));
    55         }
    56 
    57     for (int i=n;i>=k;i--)
    58     {
    59         f[n][i]=mul(f[n][i], fact[n-i]);
    60         for (int j=i+1;j<=n;j++) f[n][i]=sub(f[n][i], mul(f[n][j], C[j][i]));
    61     }
    62 
    63     IOspace::putint(f[n][k]);
    64 
    65     return 0;
    66 }
    67 inline void prepare()
    68 {
    69     std::sort(a+1, a+n+1); std::sort(b+1, b+n+1);
    70 
    71     int j=0;    
    72     for (int i=1;i<=n;i++)
    73     {
    74         for ( ;j<n && a[i]>b[j+1];j++);
    75         next[i]=j;
    76     }
    77 
    78     for (int i=0;i<=n;i++)
    79     {
    80         C[i][0]=C[i][i]=1;
    81         for (int j=1;j<i;j++)
    82             C[i][j]=add(C[i-1][j-1], C[i-1][j]);
    83     }
    84 
    85     fact[0]=1;
    86     for (int i=1;i<=n;i++) fact[i]=mul(fact[i-1], i);
    87 }
    本傻装B系列

    『——真不简单呢。不过,已经没有什么好害怕的了。』  (作死作死作死作死作死作死作死作死作死作死作死作死作死)

  • 相关阅读:
    常用的算法
    2017前端面试题
    深入了解php opcode缓存原理
    0=='aa'的结果是true
    关于PHP浮点数之 intval((0.1+0.7)*10) 为什么是7
    linux grep命令
    linux awk命令详解
    PHP socket模拟POST请求
    shell编程之sed
    Shell脚本常用判断
  • 原文地址:https://www.cnblogs.com/dyllalala/p/3900077.html
Copyright © 2020-2023  润新知