容斥原理
来源:互联网 发布:java防止重复提交 编辑:程序博客网 时间:2024/04/30 15:18
就是把每个区间的大小加到总和上,然后把每两个区间的相交部分减去,把每三个区间的相交部分加上,如此处理……
所以通常深搜比较好写,设置falg奇数时加上当前值,偶数时减去当前值,重点就是如何让求每一轮的值,注意不要重复,
深搜方向的选择,或者状压存状态,如此,如此……
eg:
HDU1796 How many integers can you find
http://acm.hdu.edu.cn/showproblem.php?pid=1796
题意:
求小于n的数中能够整除a数组中某个数的数有多少个。
思路:
可以简单求出数组中每个数在小于n的数中的答案个数,就是(n-1)/a[i],之后相加就是全部的数,但是有重复,所以要减去同时是两个数的倍数的数,
eg:a[ ] = {2,3}; sum=(n-1)/2+(n-1)/3-(n-1)/(lcm(2,3));
然而当a数组中的数多余两个时,减去的数中也会有重复,所以再加上同时是三个数的倍数的数,加上数中也会存在重复,所以需要减去四个数的倍数的数,如此……就是容斥原理了。
解题代码:
#include<iostream>#include<cstdio>using namespace std;int a[21];int n,m;long long summ;int gcd(int x,int y){ return y?gcd(y,x%y):x;}int lcm(int x,int y){ return x/gcd(x,y)*y;}void dfs(int now,int step,int flag){ summ+=(n/step)*flag; for(int i=now+1;i<m;i++) dfs(i,lcm(max(step,a[i]),min(step,a[i])),-flag);}int main(){ int i,j; while(scanf("%d%d",&n,&m)!=EOF&&n) { n--; for(i=0,j=0;i<m;i++) { scanf("%d",&a[i]); if(a[i]) a[j++]=a[i]; } m=m-(i-j); summ=0; for(i=0;i<m;i++) dfs(i,a[i],1); printf("%lld\n",summ); } return 0;}注意:
最小公倍数的求解函数,
int lcm(int x,int y)
{
return x/gcd(x,y)*y; //不能将y直接与x相乘后再除以最大公约数,因为会发生溢出。
}
1 0
- 容斥原理
- 容斥原理 POJ3904
- 【容斥原理】八
- 【八】容斥原理
- 广义容斥原理
- 容斥原理
- 容斥原理 专题
- 容斥原理 专题
- hdu4390 容斥原理
- hdu1695 容斥原理
- HDU3929(容斥原理)
- 整除 容斥原理
- HDU4390(容斥原理)
- 容斥原理
- poj3904 容斥原理
- 容斥原理应用
- bzoj2393 容斥原理
- hdu4135 容斥原理
- mount挂住失败
- Lua C 保存状态
- zookeeper
- 关于WEB集群中文件服务器的讨论
- shell 语法基础
- 容斥原理
- React Native 从入门到原理
- 【DP入门】开心的小明(01背包)
- 项目打包上架
- 浅析Spark的RangePartitioner
- Android Sensor感应器介绍(三)获取用户移动方向,指南针原理
- 存储过程返回参数的方法(也是执行动态sql 实现列名成为变量的功能)
- AtCoder Grant Contest 010 C - Cleaning dfs+逻辑+dp思想
- 关于DOM的初步认识