既然选择了远方,便只顾风雨兼|

H_W_Y

园龄:1年11个月粉丝:28关注:15

2023-08-30 15:45阅读: 43评论: 0推荐: 0

20230830-数学——容斥

20230830
自学容斥
OI-Wiki
∈∉⊂⊃⊇⊆

容斥原理

|i=1nSi|=m=1n(1)m1ai<ai+1|i=1mSai||i=1nSi|=|U||i=1nSi|

不定方程非负整数解计数

Statement

给出不定方程
i=1nxi=mn 个限制条件 xibi,其中 m,biN. 求方程的非负整数解的个数。

Solution

考虑没有限制时,答案就是 (m+n1n1)
用插板法即可证明

容斥模型

  1. 全集:没有限制时所有解的方案数
  2. 元素:变量 xi
  3. 属性:xibi

考虑原题中的方案数是这些集合的交集 |i=1nSi|
于是用容斥原理的公式可以得到答案就是 |U||i=1nSi|
而后者就可以用容斥原理来求了,
对于一些 Sai ,我们要求他们的交集
也就是说有些需要满足下限 xi>bi
考虑如何把下限去掉——
直接剪掉就可以了:
于是我们只需要用组合数去求

i=1nxi=mi=1k(bai+1)

长度为 k 的数组 a 也就相当于在枚举子集

P1450 [HAOI2008] 硬币购物

Statement

传送门
有4种不同面值的硬币,第 i 种面值的硬币价值为 Ci
当前每种硬币的数量为 di ,问有多少种购买价值为 S 的物品的方式
n103,S105

Solution

转化一下题意:
就是求 i=14Cixi=S,xidi 的非负整数解的数量
于是可以套用上面的容斥模型去完成
考虑对于全集 U 发现 S 很小,
所以可以直接用无限背包去完成即可

这道题主要就在于 4 十分特殊,
这也使得后面容斥时只有 16 种情况

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int N=1e5+5;
int c[5],n,d[5],s,m,cnt;
int ans=0,f[N];

signed main(){
  /*2023.8.30 H_W_Y P1450 [HAOI2008] 硬币购物 容斥*/ 
  scanf("%lld%lld%lld%lld%lld",&c[1],&c[2],&c[3],&c[4],&n);
  f[0]=1ll;
  for(int j=1;j<=4;j++)
    for(int i=1;i<N;i++)
      if(i>=c[j]) f[i]+=f[i-c[j]];
  for(int k=1;k<=n;k++){
    ans=0;
  	scanf("%lld%lld%lld%lld%lld",&d[1],&d[2],&d[3],&d[4],&s);
	for(int i=1;i<16;i++){
	  m=s,cnt=0;
	  for(int j=1;j<=4;j++)
	    if((i>>(j-1))&1){
	      cnt++;
	      m-=(d[j]+1)*c[j];
	    }	  	
	  if(m>=0) ans+=1ll*(cnt%2*2-1)*f[m];
	}
	printf("%lld\n",f[s]-ans); 
  }
  return 0;
}

本文作者:H_W_Y

本文链接:https://www.cnblogs.com/H-W-Y/p/17667452.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   H_W_Y  阅读(43)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起