[BZOJ1843&&2393] [Scoi2010]幸运数字]&&Cirno的完美算数教室

题目描述

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

题目分析

思路还是很简单的啦
先预处理出区间只有6 8组成的数字 然后容斥原理一波就好了
简单的学习了一下容斥原理

code:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
long long l,r,sta[5010];
void init(long long x)
{
    if(x>r) return ;
    sta[++sta[0]]=x;
    init(x*10+6),init(x*10+8);
}
long long ans;
long long gcd(long long x,long long y)
{ return !y?x:gcd(y,x%y); }
int n;
void dfs(int id,long double sum,int deep)
{
    if(sum>r) return ;
    long long nm=sum;
    if(deep&1) ans+=(r/nm-(l-1)/nm);
    else ans-=(r/nm-(l-1)/nm);
    for(int i=id+1;i<=n;i++)
    {
        long double tmp=sum/gcd(nm,sta[i]);
        if(tmp>r) continue;
        dfs(i,tmp*sta[i],deep+1);
    }
}
int cmp(long long x,long long y) { return x>y; }
int main()
{
    scanf("%lld%lld",&l,&r);
    init(0);
    for(int i=1;i<=sta[0];i++)
        for(int j=1;j<=sta[0];j++)
            if(i!=j&&sta[j]&&sta[i]%sta[j]==0) sta[i]=0;
    sort(sta+1,sta+sta[0]+1,cmp);
    for(;sta[n+1];n++);
    dfs(0,1,1);
    printf("%lld",r-(l-1)-ans);
}


code

#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
long long l,r,sta[5010];
void init(long long x)
{
    if(x>r) return ;
    sta[++sta[0]]=x;
    init(x*10+2),init(x*10+9);
}
long long ans;
long long gcd(long long x,long long y)
{ return !y?x:gcd(y,x%y); }
int n;
void dfs(int id,long double sum,int deep)
{
    if(sum>r) return ;
    long long nm=sum;
    if(deep&1) ans+=(r/nm-(l-1)/nm);
    else ans-=(r/nm-(l-1)/nm);
    for(int i=id+1;i<=n;i++)
    {
        long double tmp=sum/gcd(nm,sta[i]);
        if(tmp>r) continue;
        dfs(i,tmp*sta[i],deep+1);
    }
}
int cmp(long long x,long long y) { return x>y; }
int main()
{
    scanf("%lld%lld",&l,&r);
    init(0);
    for(int i=1;i<=sta[0];i++)
        for(int j=1;j<=sta[0];j++)
            if(i!=j&&sta[j]&&sta[i]%sta[j]==0) sta[i]=0;
    sort(sta+1,sta+sta[0]+1,cmp);
    for(;sta[n+1];n++);
    dfs(0,1,1);
    printf("%lld",r-(l-1)-ans);
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注