试题H:拯救阿拉德大陆(容斥原理+二进制枚举)

题解:

上述题意其实就是求1~n中有多少个是所给四个数字的倍数。
在这里插入图片描述
即 ans = n/a + n/b + n/c + n/d - n/lcm(a,b) - n/lcm(a,c) - n/lcm(a,d) - n/lcm(b, c) - n/lcm(b,d) - n/lcm(c,d) + n/lcm(a,lcm(b,c)) + n/lcm(a,lcm(b,d)) + n/lcm(a,lcm(c,d)) + n/lcm(b,lcm(c,d)) - n/lcm(lcm(a,b),lcm(c,d))

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll lcm(ll a,ll b){return a/__gcd(a,b)*b;}
int main()
{
    ll n,a[4],ans=0;
    cin>>n>>a[0]>>a[1]>>a[2]>>a[3];
    for(int i=1;i<(1<<4);i++){
        ll x=1;
        for(int j=0;j<4;j++){
            if(i&(1<<j)){
                x=lcm(x,a[j]);
            }
        }
        if(__builtin_popcount(i)&1)ans+=n/x;
        else ans-=n/x;
    }
    cout<<ans<<endl;
    return 0;
}
关于容斥原理:

在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复。——摘自百度百科

假设被计数的事物有A、B、C三类,则A类和B类和C类元素个数总和A∪B∪C = A+B+C - A∩B - B∩C - C∩A + A∩B∩C。

根据上式可以发现总共有C(3,1)+C(3,2)+C(3,3)=7种集合情况,为23-1个,又对于A、B、C三类有取和不取,所以我们就可以利用二进制去枚举了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
罗马尼亚问题是一个经典的搜索问题,目标是找到两个城市之间的最短路径。其中,城市之间的距离以边的权重表示,从起点到目标点的路径必须经过每个城市一次且仅一次。本题要求使用 Python 代码实现深度优先搜索,并逐个点亮。 深度优先搜索是一种基于栈的搜索方法,在搜索的过程中,先遍历一个分支的全部节点,直到该节点的所有分支都被遍历完为止,然后回溯到前一个节点,重复执行上述步骤,直至找到目标节点或搜索全部节点。在罗马尼亚问题中,栈可以用来维护搜索的节点。 具体的实现步骤如下: 1. 定义一个字典,表示罗马尼亚的地理位置和距离信息。 2. 定义一个列表,表示从起点到目标点的路径。 3. 根据深度优先搜索的特点,使用栈来保存搜索的节点。 4. 设定起点为起始节点,将其加入栈中。 5. 当栈非空时,从栈中弹出最后一个节点,并查找其相邻节点。 6. 对于每个相邻节点,如果它不在路径中,将其加入路径中,并添加到栈中。 7. 如果相邻节点是目标节点,则返回路径。 8. 重复执行步骤5-7,直至栈为空,返回空列表。 实现代码如下: ```python romania_map = { 'Arad': {'Zerind': 75, 'Sibiu': 140, 'Timisoara': 118}, 'Bucharest': {'Urziceni': 85, 'Pitesti': 101, 'Giurgiu': 90, 'Fagaras': 211}, 'Craiova': {'Dobreta': 120, 'Rimnicu Vilcea': 146, 'Pitesti': 138}, 'Dobreta': {'Mehadia': 75, 'Craiova': 120}, 'Eforie': {'Hirsova': 86}, 'Fagaras': {'Sibiu': 99, 'Bucharest': 211}, 'Giurgiu': {'Bucharest': 90}, 'Hirsova': {'Urziceni': 98, 'Eforie': 86}, 'Iasi': {'Neamt': 87, 'Vaslui': 92}, 'Lugoj': {'Timisoara': 111, 'Mehadia': 70}, 'Mehadia': {'Dobreta': 75, 'Lugoj': 70}, 'Neamt': {'Iasi': 87}, 'Oradea': {'Zerind': 71, 'Sibiu': 151}, 'Pitesti': {'Rimnicu Vilcea': 97, 'Bucharest': 101, 'Craiova': 138}, 'Rimnicu Vilcea': {'Sibiu': 80, 'Pitesti': 97, 'Craiova': 146}, 'Sibiu': {'Arad': 140, 'Oradea': 151, 'Fagaras': 99, 'Rimnicu Vilcea': 80}, 'Timisoara': {'Arad': 118, 'Lugoj': 111}, 'Urziceni': {'Bucharest': 85, 'Vaslui': 142, 'Hirsova': 98}, 'Vaslui': {'Urziceni': 142, 'Iasi': 92}, 'Zerind': {'Arad': 75, 'Oradea': 71} } def dfs(start, goal, path=[]): path = path + [start] if start == goal: return path if start not in romania_map: return None for city in romania_map[start]: if city not in path: dfs_path = dfs(city, goal, path) if dfs_path: return dfs_path return None path = dfs('Arad', 'Bucharest') for city in path: print(f'Point {city} is Lightened') ``` 此代码使用深度优先搜索算法在罗马尼亚地图中找到从阿拉德到布加勒斯特的最短路径,并逐个点亮路径中的城市。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值