zoukankan      html  css  js  c++  java
  • COGS 513 八

    513. 八

    http://www.cogs.pro/cogs/problem/problem.php?pid=513

    ★☆   输入文件:eight.in   输出文件:eight.out   简单对比
    时间限制:1 s   内存限制:128 MB

    【问题描述】

    八是个很有趣的数字啊。八=发,八八=爸爸,88=拜拜。当然最有趣的还是8用二进制表示是1000。怎么样,有趣吧。当然题目和这些都没有关系。 
    某个人很无聊,他想找出[a,b]中能被8整除却不能被其他一些数整除的数。

    【输入文件】

    第一行一个数n,代表不能被整除的数的个数。第二行n个数,中间用空格隔开。第三行两个数a,b,中间一个空格。

    【输出文件】

    一个整数,为[a,b]间能被8整除却不能被那n个数整除的数的个数。

    【样例输入】 
    eight.in

    3
    7764 6082 462
    2166 53442
    【样例输出】

    eight.out 
    6378

    【数据规模】 
    对于30%的数据, 1≤n≤5,1≤a≤b≤100000。 
    对于100%的数据,1≤n≤15,1≤a≤b≤10^9,N个数全都小于等于10^4大于等于1。

    容斥原理

    全集Z=能被8整除的数

    性质p1为能被n1整除,p2为不能被8整除,能被n2整除……

    ans=Z中不包含任意性质p的数

    这些数都有一个前提:在Z中,所以最小公倍数初值为8

    dfs过程中遇到的障碍:

    求好几个数的lcm时,

    没有必要for枚举几个数,在枚举哪几个数

    容斥原理所有项的加加减减都是集合的所有子集

    所以dfs时只需分这个数加不加入这个子集即可

    这样计算n个数的lcm时,还可利用计算的n-1个数的lcm结果

    递归式写法:

    #include<cstdio>
    using namespace std;
    int n,ans;
    long long a,b,f[10001];
    int cal(long long m)
    {
        return b/m-(a-1)/m;
    }
    long long gcd(long long x,long long y)
    {
        return y ? gcd(y,x%y):x;
    }
    long long lcm(long long x,long long y)
    {
        return x*y/gcd(x,y);
    }
    void dfs(int now,long long num,int sum)
    {
        if(now==n+1)
        {
            int s=cal(num);
            if(sum%2) ans-=s;
            else ans+=s;
            return;
        }
        long long next=lcm(num,f[now]);
        dfs(now+1,next,sum+1);
        dfs(now+1,num,sum);
    }
    int main()
    {
        freopen("eight.in","r",stdin);
        freopen("eight.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%lld",&f[i]);
        scanf("%lld%lld",&a,&b);
        dfs(1,8,0);
        printf("%d",ans);
    }

    非递归写法:

    利用二进制生成子集

    #include<cstdio>
    using namespace std;
    int n,ans;
    long long a,b,f[10001];
    int cal(long long m)
    {
        return b/m-(a-1)/m;
    }
    long long gcd(long long x,long long y)
    {
        return y ? gcd(y,x%y):x;
    }
    long long lcm(long long x,long long y)
    {
        return x*y/gcd(x,y);
    }
    int main()
    {
        freopen("eight.in","r",stdin);
        freopen("eight.out","w",stdout);
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%lld",&f[i]);
        scanf("%lld%lld",&a,&b);
        int sum=1<<n,cnt;
        ans=b/8-(a-1)/8;
        long long lcmm;
        for(int i=1;i<sum;i++)
        {
            cnt=0;lcmm=8;
            for(int j=0;j<n;j++) 
             if(i&(1<<j)) lcmm=lcm(lcmm,f[j]),cnt++;
            if(cnt&1) ans-=b/lcmm-(a-1)/lcmm;
            else ans+=b/lcmm-(a-1)/lcmm;
        }
        printf("%d",ans);
    }
  • 相关阅读:
    ASCII码
    cron表达式学习
    mysql学习二、SQL常用数据类型
    mysql学习一 常用语句
    python学习
    搬砖
    新接触Linux 命令
    搬砖
    python encode decode
    201521123071 《JAVA程序设计》第十二周学习总结
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6623380.html
Copyright © 2011-2022 走看看