• scoi2010 幸运数字


    P2567 [SCOI2010]幸运数字

    https://luogu.lohu.info/problem/show?pid=2567

    题目描述

    在中国,很多人都把6和8视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字6和8的那些号码,比如68,666,888都是“幸运号码”!但是这种“幸运号码”总是太少了,比如在[1,100]的区间内就只有6个(6,8,66,68,86,88),于是他又定义了一种“近似幸运号码”。lxhgww规定,凡是“幸运号码”的倍数都是“近似幸运号码”,当然,任何的“幸运号码”也都是“近似幸运号码”,比如12,16,666都是“近似幸运号码”。

    现在lxhgww想知道在一段闭区间[a, b]内,“近似幸运号码”的个数。

    输入输出格式

    输入格式:

    输入数据是一行,包括2个数字a和b

    输出格式:

    输出数据是一行,包括1个数字,表示在闭区间[a, b]内“近似幸运号码”的个数

    输入输出样例

    输入样例#1:
    1 10
    输出样例#1:
    2

    说明

    对于30%的数据,保证1<=a<=b<=1000000

    对于100%的数据,保证1<=a<=b<=10000000000

    容斥原理

    直接计算会TLE,因为lcm会爆掉long long

    所以2个优化:
    1、幸运号码中,若i是j的倍数,去掉i

    2、最重要的:计算lcm时,用类型double,判断lcm是否会超过b,不超过b才运算

    double:负值取值范围为 -1.7976E+308 到 -4.94065645841246544E-324,正值取值范围为 4.94065645841246544E-324 到 1.797693E+308

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    using namespace std;
    LL a,b,ans,g[10000],lu[10000],tot;
    int cnt;
    bool v[10000];
    LL pre()
    {
        g[1]=6;g[2]=8;
        int h;
        for(h=1,cnt=2;g[h]<=b;h++)
        {
            g[++cnt]=g[h]*10+6;
            g[++cnt]=g[h]*10+8;
            while(g[cnt]>b) cnt--;
        }
        for(int i=1;i<=cnt;i++)
         if(!v[i])
          {
             lu[++tot]=g[i];
             for(int j=i+1;j<=cnt;j++)
              if(g[j]%g[i]==0)
                  v[j]=true;
          }
    }
    LL gcd(LL x,LL y)
    {
        return y ? gcd(y,x%y):x;
    }
    inline void dfs(int now,LL num,int sum)
    {
        if(now==0)
        {
            LL s=b/num-a/num;
            if(sum&1) ans-=s;
            else ans+=s;
            return;
        }
        dfs(now-1,num,sum);
        double tmp=num/gcd(num,lu[now]);
        //注意这里不能写成  double tmp=num/gcd(num,lu[now])*lu[now],然后if(tmp<=b)
        //因为num/gcd(num,lu[now])仍是long long类型,再乘可能爆了 
        if(tmp*lu[now]<=b)  dfs(now-1,num/gcd(num,lu[now])*lu[now],sum+1);
    }
    int main()
    {
        cin>>a>>b;
        pre();
        --a;
        ans=b-a;//为什么ans初值不是0 
        //因为在dfs时,会dfs到一个数都不选,此时lcm=1,ans要减去 b/1-a/1,所以这里提前加上 
        dfs(tot,1,1);
        cout<<ans;
    }

    想到了容斥原理,但没想到要去掉倍数

    想到了lcm会爆long long,要用高静,弃疗了,没想到用double先判断,超过b的不运算

  • 相关阅读:
    html5传感器
    html5 canvas手写字代码(兼容手机端)
    PHP pdo单例模式连接数据库
    PHP变量回收
    PHP不过过滤防止xss攻击的方法
    jquery监听回车
    jquery预加载显示百分比
    创建自己的代码仓库
    Luxurious Houses
    Vasya the Hipster
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6624116.html
Copyright © 2020-2023  润新知