首页 > 代码库 > [BZOJ 3622]已经没有什么好害怕的了
[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 }
『——真不简单呢。不过,已经没有什么好害怕的了。』 (作死作死作死作死作死作死作死作死作死作死作死作死作死)