dyllalala

导航

[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='\n')
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('\n'); 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系列

 

 

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

 

posted on 2014-08-08 19:52  dyllalala  阅读(2308)  评论(0编辑  收藏  举报