您的位置:首页 > 其它

bzoj1853[Scoi2010]幸运数字 容斥

2017-12-11 17:04 302 查看

1853: [Scoi2010]幸运数字

Time Limit: 2 Sec  Memory Limit: 64 MB
Submit: 3027  Solved: 1128
[Submit][Status][Discuss]

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

【数据范围】
对于30%的数据,保证1 < =a < =b < =1000000
对于100%的数据,保证1 < =a < =b < =10000000000

Source

Day1

 

简单容斥
找出区间内所有6和8构成的数,筛出他们的倍数,用ans+-

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
#define N 5000
using namespace std;
ll a,b,c
,d
,ans;int vis
,cnt,tot;
void predfs(int pos,ll val){
if(!pos){
if(val<=b)
c[++cnt]=val;
return;
}
predfs(pos-1,val*10+6);
predfs(pos-1,val*10+8);
}
bool cmp(ll a,ll b){return a>b;}
ll gcd(ll a,ll b){
if(!b)return a;
return gcd(b,a%b);
}
void dfs(int u,ll val,int ok){
if(u>tot){
if(ok&1)ans+=b/val-(a-1)/val;
else if(ok)ans-=b/val-(a-1)/val;
return;
}
dfs(u+1,val,ok);
ll g=gcd(val,d[u]);
ll lcm=val/g*d[u];
if(lcm<0||lcm>b)return;
dfs(u+1,lcm,ok+1);
}
int main(){
cin>>a>>b;
for(int i=1;i<=10;i++)
predfs(i,0);

for(int i=1;i<=cnt;i++){
if(vis[i])continue;
int fg=0;d[++tot]=c[i];
for(int j=i+1;j<=cnt;j++)
if(c[j]%c[i]==0)vis[j]=1;

}
sort(d+1,d+1+tot,cmp);
dfs(1,1,0);
cout<<ans;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: