• 计数与期望


    目录

    组合数

    卡特兰


    组合数

    对于方程:x_{1}+x_{2}+......+x_{k}=n,求有多少组非负整数解。正常插板法只适用于正整数解,两个板不能插到一个空里,为了解决这个问题我们在方程左右同时加上k,得到答案 C(n+k-1,k-1);

    Count the Arrays 

    ans=C_{m}^{n-1}*(n-2)*2^{n-3}    (n-2)指减去一个中间的最大值与一个重复值,2^(n-3)指在把数字分别放到最大数两边,此时已经有3个数字(最大值、两个相同的数——一左一右)确定下来

    1. #include
    2. using namespace std;
    3. #define int long long
    4. const int mod=998244353;
    5. int n,m;
    6. int qp(int a,int b)
    7. {
    8. int res=1;
    9. while(b)
    10. {
    11. if(b&1) res=res*a%mod;
    12. b>>=1;
    13. a=a*a%mod;
    14. }
    15. return res;
    16. }
    17. signed main()
    18. {
    19. scanf("%lld%lld",&n,&m);
    20. if(n==2)
    21. {
    22. printf("0");
    23. return 0;
    24. }
    25. int nn=1,mm=1;
    26. for(int i=m;i>=m-n+2;i--) nn=nn*i%mod;
    27. for(int i=1;i
    28. printf("%lld",nn*qp(mm,mod-2)%mod*qp(2,n-3)%mod*(n-2)%mod);
    29. return 0;
    30. }

    卡特兰

    应用:进出栈、二叉树

    其实大概可以抽象成:满足…序列中…的个数都不少于…的个数的序列有多少个

    [HNOI2009]有趣的数列 

    呃其实挺苟的 在正常处理卡特兰的时候还要处理取模,题目没有保证模是质数,我们采用分解质因数(快速幂)来处理(逆元都没法用qwq)。上下质因数的指数相减就除完了。

    1. #include
    2. using namespace std;
    3. #define int long long
    4. int n,p,ans,cnt;
    5. int prime[5000010],vis[5000010];
    6. void get_prime(int n)
    7. {
    8. for(int i=2;i<=n;i++)
    9. {
    10. if(!vis[i]) prime[++cnt]=i;
    11. for(int j=1;i*prime[j]<=n;j++)
    12. {
    13. vis[i*prime[j]]=1;
    14. if(i%prime[j]==0) break;
    15. }
    16. }
    17. }
    18. int quickpow(int aa,int bb)
    19. {
    20. int res=1;
    21. while(bb)
    22. {
    23. if(bb&1) res=aa*res%p;
    24. bb>>=1;
    25. aa=aa*aa%p;
    26. }
    27. return res;
    28. }
    29. int calc(int aa,int bb)
    30. {
    31. int res=0;
    32. while(aa)
    33. {
    34. aa/=bb;
    35. res+=aa;
    36. }
    37. return res;
    38. }
    39. int China(int aa,int bb)
    40. {
    41. int res=1,x,y;
    42. for(int i=1;i<=cnt;i++)
    43. {
    44. int pap=prime[i];
    45. int a=calc(aa,pap);
    46. int b=calc(bb,pap);
    47. int c=calc(aa-bb,pap);
    48. res=res*quickpow(pap,a-b-c)%p;
    49. }
    50. return (res+p)%p;
    51. }
    52. signed main()
    53. {
    54. scanf("%lld%lld",&n,&p);
    55. get_prime(n*2);
    56. printf("%lld",(China(n*2,n)-China(2*n,n-1)+p)%p);
    57. return 0;
    58. }

    容斥

    我就不是很理解为什么看起来非常友善的容斥在c++里这么难推式子

    [SCOI2010]幸运数字 

    1. #include
    2. using namespace std;
    3. #define int long long
    4. int a,b,ans,cnt=2,tot;
    5. int num[100010],k[100010];
    6. bool vis[1000010];
    7. int gcd(int aa,int bb)
    8. {return bb==0?aa:gcd(bb,aa%bb);}
    9. void dfs(int now,int x,int sum)
    10. {
    11. if(now==0)
    12. {
    13. int cntt=b/x-a/x;
    14. if(sum&1) ans-=cntt;
    15. else ans+=cntt;
    16. return;
    17. }
    18. dfs(now-1,x,sum);
    19. double tmp=x/gcd(x,k[now]);
    20. if(tmp*k[now]<=b) dfs(now-1,x/gcd(x,k[now])*k[now],sum+1);
    21. }
    22. signed main()
    23. {
    24. scanf("%lld%lld",&a,&b);
    25. num[1]=6,num[2]=8;
    26. for(int i=1;num[i]<=b;i++)
    27. {
    28. num[++cnt]=num[i]*10+6;
    29. num[++cnt]=num[i]*10+8;
    30. while(num[cnt]>b) cnt--;
    31. }
    32. for(int i=1;i<=cnt;i++)
    33. {
    34. if(!vis[i])
    35. {
    36. k[++tot]=num[i];
    37. for(int j=i+1;j<=cnt;j++)
    38. if(num[j]%num[i]==0)
    39. vis[j]=1;
    40. }
    41. }
    42. ans=b-a+1,a--;
    43. dfs(tot,1,1);
    44. printf("%lld",ans);
    45. return 0;
    46. }

    对于容斥,有一些真正会用到的要点,或者说是推式子的步骤:

    1. 根据题目确定要统计、排列组合的元素-->”钦定“
    2. 计算该元素会被统计多少次,同时计算它对答案的贡献
    3. 容斥进行简单的加减计算 / 枚举子集

    对于大部分容斥题目来说,经常会用到两个式子

    \sum_{i=0}^{n}C_{n}^{i} *(-1) ^{i} 

    \sum_{i=1}^{n}C_{n}^{i}*(-1)^{i-1}

    这里我们用到的是第二个式子:当统计钦定的m个幸运数的倍数的个数时,每一个数会被统计C_{n}^{m}次,对答案的贡献是(-1)^{m-1}*C_{n}^{m},即如果其是至少一个幸运数的倍数则会被统计一次,否则不被统计。

    那么这里的±1是怎么出来的呢?

    方法一:

    杨辉三角性质:

    方法二:

    刷表

    我们要做的事情就是求一些物品x在条件C下的贡献X_{C},所谓容斥就是指我们从所有X值里找到相对好求的值,再对每个条件构建一个系数f_{1},f_{2},f_{3}.....,构成式子

    \sum_{i=0}^{n}X_{C[i]}*f[i]          其中f[i]由DP打表找规律得(???)

  • 相关阅读:
    Spark 【分区与并行度】
    计算机毕业论文微信小程序毕业设计项目ssm驾校教培服务系统小程序+后台管理系统|前后分离VUE[包运行成功]
    90行代码写一个视频播放器
    Java测试题(核心基础)
    【康师傅】MySQL事务
    JavaSE - 封装、static成员和内部类
    分享几个关于Camera的坑
    【LeetCode刷题】--12.整数转罗马数字
    全局ID生成算法及使用场景,你用对了么?
    Prometheus详解(十)——Prometheus容器监控
  • 原文地址:https://blog.csdn.net/m0_60137414/article/details/125988388