星星之火OIer:机智的手机商

机智的手机商(容斥基础题)

第一眼看过去,这哪里是容斥原理的题嘛,明明就是考空间力的题嘛

乍一看还是可难的

毕竟就算告诉你具体数值去硬算都要想很久

并且还需要极强的空间力

(硬算解出来的都可以去参加最强大脑)

所以呢

我们要巧解

那么问题来了???

怎么巧解

我们首先以二维空间的题为例

比如我们先给一张图::

PS::背后不一定是正方形,将就看着

然后呢,有一束光::

这么下来的一束

我们可以发现TA穿透了6个方块

其实好像不需要这么多。。。

画完之后

我们可以发现

这束光如果进入盒子

只有有三种可能

  • 从盒子的上面的面进入
  • 从盒子左侧的面进入
  • 从盒子的左上角进入(图不是很特殊,所以在图中未能很好的体现)

其实我们也可以看到

图中的第一个盒子是从左上角进入的

我们把这束光分解一下

分解成向右和向下的

我们可以发现

从左边进入的(向右的)穿过了3个盒子

也就是  n/b=3

从上边进入的(向下的)穿过了4个盒子

也就是  n/a=4

再减去a和b的最大公约数(从左上角进入的)

也就是  n/lcm(a,b)=1

3+4-1=6

所以就是答案了

附张图::

我们由此可以推到三维空间上去::

首先计算从前面进入盒子的光线即  n/a

(画不出立体感不要在意o(>﹏<)o)

然后计算从上面进入盒子的光线即  n/b

再来计算从右面进入盒子的光线即  n/c

再来计算重叠的

从前面和上面之间的棱的进入盒子的光线即  n/lcm(a,b)

从上面和右面之间的棱的进入盒子的光线即  n/lcm(b,c)

从前面和右面之间的棱的进入盒子的光线即  n/lcm(a,c)

减去之后又还要加从顶点上进入的

即  n/lcm(a,lcm(b,c))

然后就是答案了

为神马呢???

这个光线穿过的所有的方块

只有三种情况

正如上图所示

而在这三种情况中

都有重复算的

正像接下来的三幅图

而最后棱又被多减了一次

所以还要加回来

所以这是一道容斥原理的题

其实用图来表示是这样的::

然后我们就可以上代码了::

#include<cstdio>
#include<iostream>
using namespace std;
inline void read(int &x) {
    x=0;
    int f=1;
    char s=getchar();
    while(s<'0'||s>'9') {
        if(s=='-')
            f=-1;
        s=getchar();
    }
    while(s>='0'&&s<='9') {
        x=x*10+s-48;
        s=getchar();
    }
    x*=f;
}
inline void pr(int x) {
    if(x<0) {
        putchar('-');
        x=-x;
    }
    if(x>9)
        pr(x/10);
    putchar(x%10+48);
}//快读快输不解释
int n,a,b,c;
inline int gcd(int x,int y) {
    if(x<y)
        swap(x,y);
    return y==0?x:gcd(y,x%y);
}
inline int lcm(int x,int y) {
    return x*y/gcd(x,y);
}//求最大公倍数
int main() {
    read(n),read(a),read(b),read(c);
    pr(n/a+n/b+n/c-n/lcm(a,b)-n/lcm(a,c)-n/lcm(b,c)+n/lcm(a,lcm(b,c)));//emmm。。。
}

学会这波神奇的操作了吗??

更多作者博客在这里

当然你还可以推到n维空间!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值