• SCOI2010 幸运数字


    题目链接:戳我

    lcm相关 容斥+搜索剪枝

    选一个数的近似幸运号码,但是这样子可能有两个或多个的数的倍数相同——所以考虑容斥——我们把两个的减去。但是这样一来是三个数的lcm的数的就没有计算到,我们再加上它。。。。。。

    trick1——把合法的数先预处理出来,方便之后操作。

    trick2——我们从小到大判断,如果一个数已经是前面一个数的倍数了,就无需记录它了,反正它的近似幸运数字都被包含于那个数字的近似幸运数字。

    trick3——如果当前的lcm到达了上届(也就是题目中的B)我们就无需再搜索了(显然吧)

    trick4——从大到小暴搜,可以使得lcm更快地达到上届。

    最后,我们不需要先计算出[1,r]和[1,l-1]的,然后再相减计算答案。对于一个数x,区间[A,B]内它的倍数其实就是(lfloorfrac{B}{x} floor+lceilfrac{A}{x} ceil+1)

    qwqwqwq代码如下:

     #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int tot,n;
    int done[MAXN];
    long long A,B,ans;
    long long num[MAXN],pre[MAXN];
     
    inline void init(int cnt,int limit,long long val,long long base)
    {
        //printf("cnt=%d limit=%d val=%lld base=%lld
    ",cnt,limit,val,base);
        if(cnt>limit) {pre[++tot]=val;return;}
        init(cnt+1,limit,val+6*base,base*10);
        init(cnt+1,limit,val+8*base,base*10);
    }
    
    inline bool cmp(long long x,long long y){return x>y;}
    
    inline long long gcd(long long x,long long y){return y==0?x:gcd(y,x%y);}
    
    inline long long calc(long long x)
    {
        long long cur_ans=0;
        cur_ans=B/x-A/x-(A%x!=0)+1;
        return cur_ans;
    }
    
    void search(int dep,int cnt,long long val) 
    {
        if (val>B) return;
        if (dep>n) 
    	{
            if (cnt==0) return;
            ans+=calc(val)*((cnt&1)?1:-1);
            return;
        }
        search(dep+1,cnt,val);
        long long tmp=val/gcd(val,num[dep]);
        if(1.0*tmp*num[dep]<=B)
            search(dep+1,cnt+1,tmp*num[dep]);
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        freopen("ce.out","w",stdout);
        #endif
        cin>>A>>B;
        for(int i=1;i<=10;i++) init(1,i,0,1);
        for(int i=1;i<=tot;i++)
        {
            if(!done[i]) num[++n]=pre[i];
            for(int j=i+1;j<=tot;j++)
                if(pre[j]%pre[i]==0) done[j]=1;
        }
        sort(&num[1],&num[n+1],cmp);
        search(1,0,1);
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    《人月神话》读后感
    十天冲刺计划(第二次)
    日历表的事件处理和管理(刘静)
    十天冲刺计划
    结组开发项目(TD学生助手)
    电梯调度(二)
    敏捷软件开发方法综述
    对于二维数组求子数组的和的最大值
    电梯调度(一)
    FloatyFish休闲游戏 Beta正式发布
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10432725.html
Copyright © 2020-2023  润新知