• 【bzoj1853】 Scoi2010—幸运数字


    http://www.lydsy.com/JudgeOnline/problem.php?id=1853 (题目链接)

    今天考试考了容斥,结果空知道结论却不会写→_→

    题意

      求区间中不含6,8两个数字及由6,8组成的数字的倍数的的数有几个。

    Solution

      容斥原理

      先把所有的幸运数字都蒯到一个数组里,将两两之间可以整除的数只留下一个小的。 

      接下来如果暴力组合统计答案的话肯定会TLE,因为就算去掉了可以被整除的数以后还是有1000多个幸运数字。我们考虑dfs,x记录当前已经枚举到了第几个数,y记录已经选了几个数,z表示这几个数的最小公倍数。从大往小枚举,然后加个剪枝,这个神奇的剪枝就直接把复杂度大大降低了,其实就是当最小公倍数大于上界r时返回→_→

      为什么会这样呢,我想了下。只有当前位数T比较大的情况下,T位幸运数字才会比较多,而当T比较大的情况下,两个幸运数字的lcm(最小公倍数)就会很大,很有可能超越上界,所以这个剪枝是很有效的。

    代码

    // bzoj1853
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define inf 2147483640
    #define LL long long
    #define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
    using namespace std;
    inline LL getint() {
        LL x=0,f=1;char ch=getchar();
        while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int n,m,vis[100010];
    LL l,r,ans,a[100010],b[100010];
    
    void pre(int x,LL y) {
        if (y>r)return;
        if (x>0) a[++m]=y;
        pre(x+1,y*10+6);
        pre(x+1,y*10+8);
    }
    LL gcd(LL x,LL y) {
        return x%y==0?y:gcd(y,x%y);
    }
    void dfs(int x,int y,LL z) {
        if (x>n) {
            if (y&1) ans+=r/z-(l-1)/z;
            else if (y) ans-=r/z-(l-1)/z;
            return;
        }
        dfs(x+1,y,z);
        LL tmp=z/gcd(a[x],z);
        if ((double)a[x]*tmp<=r) dfs(x+1,y+1,a[x]*tmp);
    }
    int main() {
        scanf("%lld%lld",&l,&r);
        pre(0,0);
        sort(a+1,a+1+m);
        memset(vis,0,sizeof(vis));
        for (int i=1;i<=m;i++) if (!vis[i]) {
                for (int j=i+1;j<=m;j++)
                    if (a[j]%a[i]==0) vis[j]=1;
                b[++n]=a[i];
            }
        for (int i=1;i<=n;i++) a[n-i+1]=b[i];
        dfs(1,0,1);
        printf("%lld",ans);
        return 0;
    }
    

      

  • 相关阅读:
    Pandas包对多个数据表(DataFrame)的常用整合功能。
    pandas numpy 简单应用 loandata
    榛果 美团 登录 爬虫 requests session
    python 日期循环
    opencv 验证码 识别
    运行MapReduce任务
    CenOS安装MySQL服务
    leetcode 67. 二进制求和
    最近对一些领域比较感兴趣,这里列举出来供以后查阅
    leet code 1014. 最佳观光组合
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5914580.html
Copyright © 2020-2023  润新知