leetcode刷题系列三。这一节的内容主要是容斥原理的题目和题解。
百度百科上容斥原理的解释:
在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理
公式
两个集合的容斥关系公式:A∪B =|A∪B| = |A|+|B| - |A∩B |(∩:重合的部分)
三个集合的容斥关系公式:|A∪B∪C|= |A|+|B|+|C| - |A∩B| - |B∩C| - |C∩A| + |A∩B∩C|
例题
算法分析
//求最大公约数
#define ll long long
int gad(int a,int b)
{
return b==0?a:gad(b,a%b);
}
//求最小公倍数
ll lcm(int a,int b)
{
return a*b/gad(a,b);
}
int getabc(int n,int a,int b,int c)
{
ll num1=lcm(a,b);
ll num2=lcm(b,c);
ll num3=lcm(a,c)
ll ans=n/a+n/b+n/c-n/lcm(a,b)-n/lcm(a,c)-n/lcm(b,c)+n/lcm(num1,lcm(num2,num3));
return ans;
}
题目一
#define ll long long
ll gcd(int a,int b)
{
return b==0? a:gcd(b,a % b);
}
ll lcm(int a, int b)
{
return a / gcd(a,b) * b;
}
int MIN(ll a, ll b)
{
return a < b? a: b;
}
int nthUglyNumber(int n, int a, int b, int c)
{
ll num1 = lcm(a,b);
ll num2 = lcm(b,c);
ll num3 = lcm(a,c);
ll num0 = lcm(num1,lcm(num2,num3));
int min = MIN(a,MIN(b,c));
ll left = min;
ll right = min * n;
ll mid = 0;
while(left < right)
{
mid = (left + right) / 2;
int sum = mid / a + mid / b + mid / c - mid /num1 - mid / num2 -mid / num3 + mid / num0;
if(sum >= n)
right = mid;
else if(sum < n)
left = mid + 1 ;
}
return right;
题目二
思路:考虑 dp[i][j]。最后一首歌,我们可以播放没有播放过的歌也可以是播放过的。如果未播放过的,那么就是 dp[i-1][j-1] * (N-j) 种选择方法。如果不是,那么就是选择之前的一首歌,dp[i-1][j] * max(j-K, 0)(j 首歌,最近的 K 首不可以播放)。
class Solution {
public:
int numMusicPlaylists(int n, int len, int dis) {
int mod=1e9+7;
long dp[101][101];
memset(dp,0,sizeof(dp));
dp[0][0]=1;
//i为听过歌的数量
//j为听了多少首歌
//dis是歌曲间隔
for(int i=1;i<=n;i++)
{
for(int j=1;j<=len;j++)
{
dp[i][j]+=dp[i][j-1]*max(0,(i-dis));
dp[i][j]+=dp[i-1][j-1]*(n-(i-1));
dp[i][j]%=mod;
}
}
return dp[n][len];
}
};
总结
写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个关于 java开发 的学习思路及方向。从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。
由于内容较多就只放上一个大概的大纲,需要更及详细的学习思维导图的 点击我的Gitee获取。
还有 高级java全套视频教程 java进阶架构师 视频+资料+代码+面试题!
全方面的java进阶实践技术资料,并且还有技术大牛一起讨论交流解决问题。