zoukankan      html  css  js  c++  java
  • bzoj 1853: [Scoi2010]幸运数字

    1853: [Scoi2010]幸运数字


    2017-08-27


    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
    【样例输入3】

    23333 6666666


    Sample Output

    【样例输出1】
    2
    【样例输出2】
    809
    【样例输出3】
    1751660

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


    这个题先进行一遍dfs找到所有满足条件的数(只有‘6’|‘8’)的数(并且小于右端点)。放进集合A

    然后再集合A中删去所有A[i]>A[j]且A[i]%A[j]==0的数。why?不想证

    那么咱们怎么根据删去数后的A快速求出在区间有多少呢?

    显然在区间[1,r]的区间能整除k的数只有[r/k]。

    但是这样又会把任意两个数的最小公倍数算两次>_>(wa)

    所以我们还要算一遍任意两数的最小公倍数,减去它们!然后就又算少了QwQ.

    ↑就是为什么要去掉部分数的原因poi

    递归来求不同数的lcm,不停的加减,最后就A掉了x

    两个数a,b的lcm=a*b/gcd(a,b);gcd(a,b)<=a,b

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define ll long long 
    using namespace std;
    int cnt;
    ll gcd(ll x,ll y){
        if(y==0)return x;
        else return gcd(y,x%y);
    }
    ll l,r,n,m,ans;
    ll a[5000],b[5000];
    bool rem[5000];
    void add(int x,ll y){
         if(y>r)return;
         if(x)n++,a[n]=y;
         add(x+1,y*10+6);
         add(x+1,y*10+8);
    }
    void dfs(int x,int y,ll now){
        if(x>m){
            if(y&1)ans+=r/now-l/now;
            else if(y)ans-=r/now-l/now;
            return ;
        }
        dfs(x+1,y,now);
        ll re=now/gcd(now,a[x]);
        if(((double)re*a[x])<=r)
            dfs(x+1,y+1,re*a[x]);
    }
    int main(){
        cin>>l>>r;l--;
        add(0,0);
        sort(a+1,a+1+n);
        for(int i=1;i<=n;++i){
            if(!rem[i]){
                m++,b[m]=a[i];
                for(int j=i+1;j<=n;j++)
                if(!(a[j]%a[i]))rem[j]=1;
            }
        }
        for(int i=1;i<=m;i++){a[m+1-i]=b[i];}
        dfs(1,0,1);
        cout<<ans;
        return 0;
    }
    Lucky_Integer

    符号优先有毒

    by:s_a_b_e_r


     

    先求出所有lucky number丢进数组a

    然后去掉一些多余的数字

    比如6和666都是lucky number

    但是666是6的倍数

    所以666可以去掉

    why?不想证你不想证我来证

    666作为一个luckynumber,因为是luckynumber6的倍数,所以它同时也是一个近似luckynumber

    所以把它删去之后它在之后的计算中还会被重新算回来

    所以出于复杂度考虑就把它删去了……666同学走好x

    接着dfs一遍计算答案个数

    dfs(x,y,z)表示目前处理到luckynumber第x个数,已经选了y个数,这y个数的lcm(最小公倍数)是z

    每次把ans加上每个数,减去每两个数的lcm,加上每三个数的lcm,减去每四个数的lcm……

    这样,就OK了w

    附代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long 
    using namespace std;
    const int N=10001;
    ll l,r,ans,a[N],b[N];
    int cnt,n;
    bool vis[N];
    ll gcd(ll a,ll b){if(b==0)return a;return gcd(b,a%b);}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    void lun(int x,ll y)
    {
         if(y>r)return;
         if(x>0)a[++cnt]=y;
         lun(x+1,y*10+6);
         lun(x+1,y*10+8);
    }
    void dfs(int x,int y,ll z)
    {
         if(x>n)
         {
           if(y%2)ans+=r/z - (l-1)/z;
           else if(y)ans-=r/z - (l-1)/z;
           return;
         }
         dfs(x+1,y,z);
         ll t=z/gcd(a[x],z);
         if(((double)a[x]*t)<=r)dfs(x+1,y+1,a[x]*t);
    }
    int main()
    {
        cin>>l>>r;
        lun(0,0);
        sort(a+1,a+cnt+1);
        for(int i=1;i<=cnt;++i)
        {
          if(vis[i])continue;
          b[++n]=a[i];
          for(int j=i+1;j<=cnt;++j)
            if(!(a[j]%b[n]))vis[j]=1;
        }
        for(int i=1;i<=n;++i)a[n-i+1]=b[i];
        dfs(1,0,1);
        cout<<ans<<endl;
        return 0;
    }
    1853(wypx)

    符号优先有毒+1,'!'优先级>'%',害的我俩TLE好多发qwq

    by:wypx


    s:感觉steam那个桌面好棒啊

    w:日常沉迷小姐姐x

  • 相关阅读:
    arcengine 文件夹连接
    [WinForm]DataGridView列头右键菜单
    Arcengine编辑代码
    map与pagelayout同步新方法
    清华教授李稻葵:恒昌、宜信过去三四年走过了西方国家20年的历程!
    delete
    股权融资与债务融资之区别 创业者一定要看懂
    《乌镇指数:全球人工智能发展报告2016》正式发布
    2017年美国名校录取中国大陆学生数据汇总
    IDG资本全球拼图:近10年揽26家独角兽,最敢出手VC再造"VC+"
  • 原文地址:https://www.cnblogs.com/ck666/p/7441165.html
Copyright © 2011-2022 走看看