zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    ie6动态创建iframe无法显示内容的bug
    时间字符串解析
    自定义时间格式转换代码
    MySql存储过程异常处理示例
    解析数字签名的Substring结构
    自动输出类的字段及值
    深复制与浅复制的实现
    ie版本过低提示升级ie的示例
    Web安全攻防TCP/IP安全篇
    不同网段相互通信实验
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10432725.html
Copyright © 2011-2022 走看看