[luogu5339] [TJOI2019]唱、跳、rap和篮球(容斥原理+组合数学)(不用NTT)

题面

分析

首先考虑容斥,求出有i堆人讨论的方案。

可以用捆绑法,把每堆4个人捆绑成一组,其他人每个人一组。这样一共有\(n-3i\)组(这些组可以被看成相同的点)。

我们从中选出n-4i个点,这些点展开成1个人,其他\(i\)个点展开成4个人。那么方案数就是\(C_{n-3i}^{n-4i}\)

由于\(i\)堆人的喜好已经确定,最终答案为\(\sum_{i=0}^n (-1)^i \times C_{n-3i}^{n-4i} \times (n-4i个单独的人的喜好方案数)\)

那么我们就需要求n-4i个单独的人的喜好方案数。每种喜好的人各有\(a-i,b-i,c-i,d-i\)。假如这些人里每种喜好的人各有\(x,y,z,w(x \leq a-i,y \leq b-i,z \leq c-i,w \leq d-i,x+y+z+w=n-4i)\)个。这是一个有重复元素的排列问题。答案是\(\frac{(n-4i)!}{x!y!z!w!}\)

直接枚举的时间复杂度为\(O(k^4)\),(\(k=\min(a,b,c,d)\)),下同。显然会超时。我们可以用折半搜索的思想,先枚举前两个的个数\(x,y\),把\(\frac{1}{x!y!}\)的和记录在\(cnt[x+y]\)中。然后枚举\(z,w\),只要每次答案累加上\(z!\times w! \times cnt[n-4i-(z+w)]\)即可。时间复杂度\(O(k^2)\)

总时间复杂度\(O(nk^2)\)

代码

  1. //鸡你太美!
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #define mod 998244353
  6. #define maxn 1000
  7. using namespace std;
  8. typedef long long ll;
  9. inline ll fast_pow(ll x,ll k){
  10. ll ans=1;
  11. while(k){
  12. if(k&1) ans=ans*x%mod;
  13. x=x*x%mod;
  14. k>>=1;
  15. }
  16. return ans;
  17. }
  18. inline ll inv(ll x){
  19. return fast_pow(x,mod-2);
  20. }
  21. int n,a,b,c,d;
  22. ll fact[maxn+5],invfact[maxn+5];
  23. void ini(){
  24. fact[0]=1;
  25. for(int i=1;i<=n;i++) fact[i]=fact[i-1]*i%mod;
  26. invfact[n]=inv(fact[n]);
  27. for(int i=n-1;i>=0;i--) invfact[i]=invfact[i+1]*(i+1)%mod;
  28. }
  29. inline ll C(ll n,ll m){
  30. return fact[n]*invfact[n-m]%mod*invfact[m]%mod;
  31. }
  32. ll cnt[maxn+5];
  33. int main(){
  34. scanf("%d",&n);
  35. scanf("%d %d %d %d",&a,&b,&c,&d);
  36. ini();
  37. int mx=min(min(a,b),min(c,d));
  38. ll ans=0;
  39. for(int i=0;i<=n/4&&i<=mx;i++){
  40. memset(cnt,0,sizeof(cnt));
  41. //可重排列((a+b+c+d)!)(a!b!c!d!)
  42. //类似中途相遇分两半求解
  43. for(int j=0;j<=a-i;j++){
  44. for(int k=0;k<=b-i;k++){
  45. cnt[j+k]=(cnt[j+k]+invfact[j]*invfact[k]%mod)%mod;
  46. }
  47. }
  48. ll sum=0;
  49. for(int j=0;j<=c-i;j++){
  50. for(int k=0;k<=d-i&&j+k<=n-4*i;k++){
  51. sum=(sum+cnt[n-4*i-(j+k)]*invfact[j]%mod*invfact[k]%mod)%mod;
  52. }
  53. }
  54. sum=sum*fact[n-4*i]%mod;
  55. //捆绑法,把4个一组的捆绑成1个,共n-3i个
  56. //再从中选出n-4i个单独1个的,其他展开
  57. //C(n-3i,n-4i)
  58. ans+=fast_pow(-1,i)*C(n-3*i,n-4*i)*sum%mod;
  59. ans=(ans+mod)%mod;
  60. }
  61. printf("%lld\n",ans);
  62. }

[luogu5339] [TJOI2019]唱、跳、rap和篮球(容斥原理+组合数学)(不用NTT)的更多相关文章

  1. [bzoj5510]唱跳rap和篮球

    显然答案可以理解为有(不是仅有)0对情况-1对情况+2对情况-- 考虑这个怎么计算,先计算这t对情况的位置,有c(n-3t,t)种情况(可以理解为将这4个点缩为1个,然后再从中选t个位置),然后相当于 ...

  2. Luogu5339 [TJOI2019]唱、跳、rap和篮球 【生成函数,NTT】

    当时看到这道题的时候我的脑子可能是这样的: My left brain has nothing right, and my right brain has nothing left. 总之,看到&qu ...

  3. [TJOI2019]唱、跳、rap和篮球——容斥原理+生成函数

    先附一组sd图 然后放上原题链接 注意,队伍不同指的是喜好不同,不是人不同 先想到\(DP\),然后你会发现并没有什么优秀的状态设计,然后我们考虑容斥 设\(lim\)表示选的癌坤组数的上限,\(f_ ...

  4. [LOJ3106][TJOI2019]唱、跳、rap和篮球:DP+生成函数+NTT+容斥原理

    分析 令\(f(i)\)表示共\(i\)组同学讨论cxk的位置的方案数(不考虑其他位置上的人的爱好),这个数组可以很容易地通过依次考虑每个位置是否是四个人中最后一个人的位置来递推求解,时间复杂度\(O ...

  5. 将Android手机无线连接到Ubuntu实现唱跳Rap

    您想要将Android设备连接到Ubuntu以传输文件.查看Android通知.以及从Ubuntu桌面发送短信 – 你会怎么做?将文件从手机传输到PC时不要打电话给自己:使用GSConnect就可以. ...

  6. [TJOI2019]唱、跳、rap和篮球_生成函数_容斥原理_ntt

    [TJOI2019]唱.跳.rap和篮球 这么多人过没人写题解啊 那我就随便说说了嗷 这题第一步挺套路的,就是题目要求不能存在balabala的时候考虑正难则反,要求必须存在的方案数然后用总数减,往往 ...

  7. [TJOI2019]唱、跳、rap和篮球——NTT+生成函数+容斥

    题目链接: [TJOI2019]唱.跳.rap和篮球 直接求不好求,我们考虑容斥,求出至少有$i$个聚集区间的方案数$ans_{i}$,那么最终答案就是$\sum\limits_{i=0}^{n}(- ...

  8. 「TJOI2019」唱、跳、rap 和篮球 题解

    题意就不用讲了吧-- 鸡你太美!!! 题意: 有 \(4\) 种喜好不同的人,分别最爱唱.跳. \(rap\).篮球,他们个数分别为 \(A,B,C,D\) ,现从他们中挑选出 \(n\) 个人并进行 ...

  9. 【bzoj4710】[Jsoi2011]分特产 容斥原理+组合数学

    题目描述 JYY 带队参加了若干场ACM/ICPC 比赛,带回了许多土特产,要分给实验室的同学们. JYY 想知道,把这些特产分给N 个同学,一共有多少种不同的分法?当然,JYY 不希望任何一个同学因 ...

随机推荐

  1. 数据结构-STL序列式容器总结

    根据序列在容器中的排列特性,将常见数据结构分为:序列式容器和关联式容器. 常见序列式容器有 1.array(build-in)c++內建 2.vector 3.heap(以算法方式呈现) 4.prio ...

  2. linux 硬件时间 系统时间

    建了一个虚拟机,发现每次重启后系统时钟总是跟现有时间相差10多个小时 用date -s进行修正之后,再次重启又出现该问题.于是怀疑跟硬件时钟有关 用hwclock看了下,发现的确硬件时钟的时间存在差异 ...

  3. BZOJ 4289: PA2012 Tax Dijkstra + 查分

    Description 给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边 ...

  4. 3-Gitblit服务器搭建及IDEA整合Git使用

    背景:虽然有GitHub.GitLab这样强大的Git仓库,但是涉及私有Git库要收费,所以自己动手搭建免费的用用 环境:windows 7 旗舰版.JDK 1.8.IDEA 2017 ------- ...

  5. css命名和书写规范

    前言 在项目开发中对于css名字的命名和书写老是感觉很混乱,这对于代码的可读性以及维护提出了挑战,所以在闲暇之余看了一些这方面的内容,现总结如下... 1.命名规则说明 所有的命名最好都小写 属性的值 ...

  6. SQL server 安装教程

      双击sql server 2008的.exe安装文件,进入[SQL Server 安装中心]. 点击界面左侧的[安装],然后点击右侧的[全新SQL Server 独立安装或向现有安装添加功能],进 ...

  7. Linux下GCC去除调试信息

    如果不去除调试信息,直白点说基本上是把代码公开了,不要带-g参数,还有就是需要带 -O2 -fvisibility=hidden -s 生成程序后可以用命令strip进一步去除不需要的符号 strip ...

  8. Word2Vec模型参数 详解

    用gensim函数库训练Word2Vec模型有很多配置参数.这里对gensim文档的Word2Vec函数的参数说明进行翻译,以便不时之需. class gensim.models.word2vec.W ...

  9. 文件的权利和sudoers中规定的权限哪个更大?

    文件的权利和sudoers中规定的权限哪个更大? 当然是文件的权限更大!!! 这也是linux的 更安全的根本所在! 就是它的每一个文件都有严格的 rwxr--r-- 权限规定. 只有文件权限规定了的 ...

  10. jest 事件测试

    概述 最近玩 Jest,测试 Vue 组件上的事件,有一些心得,记录下来供以后开发时参考,相信对其他人也有用. 事件测试 对于 Vue 组件上的事件,分为 2 种,一种是子组件 Emit 的事件,另一 ...