我是靠谱客的博主 笑点低雪碧,最近开发中收集的这篇文章主要介绍容斥原理练习题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1. bzoj 2393&nefu 1795 Cirno的完美算数教室

http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1795

Description
Cirno发现了一种baka数,这种数只含有2和9两种数字
现在Cirno想知道一个区间中有多少个数能被baka数整除
但是Cirno这么天才的妖精才不屑去数啦
只能依靠聪明的你咯。
Input
一行正整数L R
( 1 < L < R < 10^10)
Output
一个正整数,代表所求的答案
Sample Input
1 100
Sample Output
58

容斥原理:先求出区间内所有baka数,去掉其中是baka数倍数的那些数,因为它们的作用是等价的。区间内被一个baka数整除的个数-被2个baka数公倍数整除的+3个公倍数整除的-…
dfs也不知道写的什么,莫名其妙就过了,觉得可能林大oj数据太弱,结果在bzoj也没找到这个题…所以到底过不过,还不一定…
代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
const ll maxn=1e10+5;
ll baka[2100],vis[2100];
ll l,r,ans;
int cnt,tnt;
void f(ll x)
{
if(x>r)
return;
baka[cnt++]=x;
f(x*10+2);
f(x*10+9);
}
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
void dfs(ll cou,ll mul,ll sum,ll tag)
{
if(mul>tag)
return;
if(sum!=0&&cou==tnt)
{
if(sum&1)
ans+=tag/mul;
else
ans-=tag/mul;
return;
}
if(cou==tnt)
return;
dfs(cou+1,mul,sum,tag);
ll tmp=mul/gcd(mul,baka[cou+1])*baka[cou+1];
dfs(cou+1,tmp,sum+1,tag);
}
ll rc(ll x)
{
ans=0;
dfs(-1,1,0,x);
return ans;
}
int main()
{
scanf("%lld%lld",&l,&r);
f(0);
sort(baka,baka+cnt);
for(int i=1; i<cnt; i++)
{
for(int j=i+1; j<cnt; j++)
{
if((vis[j]==0)&&(baka[j]%baka[i]==0))
vis[j]=1;
}
}
for(int i=1; i<cnt; i++)
if(vis[i]==0)
baka[tnt++]=baka[i];
cout<< rc(r)-rc(l-1)<<endl;;
return 0;
}

2. bzoj 18533&nefu 1794 幸运数字-容斥

http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1794
Description
在中国,很多人都把6和8视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字6和8的那些号码,比如68,666,888都是“幸运号码”!但是这种“幸运号码”总是太少了,比如在[1,100]的区间内就只有6个(6,8,66,68,86,88),于是他又定义了一种“近似幸运号码”。lxhgww规定,凡是“幸运号码”的倍数都是“近似幸运号码”,当然,任何的“幸运号码”也都是“近似幸运号码”,比如12,16,666都是“近似幸运号码”。 现在lxhgww想知道在一段闭区间[a, b]内,“近似幸运号码”的个数。
Input
输入数据是一行,包括2个数字a和b
Output
输出数据是一行,包括1个数字,表示在闭区间[a, b]内“近似幸运号码”的个数
Sample Input
「样例输入1」
1 10
「样例输入2」
1234 4321
Sample Output
「样例输出1」
2
「样例输出2」
809
Hint
对于100%的数据,保证1 < =a < =b < =10000000000
代码
跟上一个题一模一样,但数据太大,剪枝优化不然会超时,通过给幸运数字数组从大到小排序,这样dfs会先选择大数,则省去了许多不必要的分支。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
ll baka[3000],vis[3000];
ll l,r,ans;
int cnt,tnt;
void f(ll x)
{
if(x>r)
return;
baka[cnt++]=x;
f(x*10+8);
f(x*10+6);
}
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
void dfs(ll cou,ll mul,ll sum,ll tag)
{
if(mul>tag)
return;
if(sum!=0&&cou==tnt)
{
if(sum&1)
ans+=tag/mul;
else
ans-=tag/mul;
return;
}
if(cou==tnt)
return;
dfs(cou+1,mul,sum,tag);
double tmp=(double)mul/(double)gcd(mul,baka[cou+1])*(double)baka[cou+1];
if(tmp>r) return;
dfs(cou+1,tmp,sum+1,tag);
}
ll rc(ll x)
{
ans=0;
dfs(-1,1,0,x);
return ans;
}
bool cmp(ll a,ll b)
{
return a>=b;
}
int main()
{
scanf("%lld%lld",&l,&r);
f(0);
sort(baka,baka+cnt);
for(int i=1; i<cnt; i++)
{
for(int j=i+1; j<cnt; j++)
{
if((vis[j]==0)&&(baka[j]%baka[i]==0))
vis[j]=1;
}
}
for(int i=1; i<cnt; i++)
if(vis[i]==0)
baka[tnt++]=baka[i];
sort(baka,baka+tnt,cmp);
//排序
cout<< rc(r)-rc(l-1)<<endl;;
return 0;
}

最后

以上就是笑点低雪碧为你收集整理的容斥原理练习题的全部内容,希望文章能够帮你解决容斥原理练习题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部