zoukankan      html  css  js  c++  java
  • [2019.1.10]BZOJ1853 [Scoi2010]幸运数字

    首先,我们可以预处理(r)以内的幸运数字。

    这样的数字不会很多,设(r)内所有幸运数字有(n)个,分别是(a_1,a_2,a_3,...,a_n)

    然后,我们知道(m)以内的(x)的倍数有(lfloorfrac{m}{x} floor)个。

    那么答案就是(sum_{i=1}^nlfloorfrac{r}{a_i} floor-sum_{i=1}^nlfloorfrac{l-1}{a_i} floor)?

    当然不是,因为会有重复。

    所以考虑容斥。

    我们设(f(m,x)=sum_{i_1=1}^nsum_{i_2=i_1+1}^nsum_{i_3=i_2+1}^n...sum_{i_x=i_{x-1}+1}^nlfloorfrac{m}{lcm(p_{i_1},p_{i_2},p_{i_3},...,p_{i_n})} floor),即任意(x)个幸运数字的最小公倍数 小于等于(m)的倍数数量和。

    那么答案就是(sum_{i=1}^n(-1)^{i+1}f(r,i)-sum_{i=1}^n(-1)^{i+1}f(l-1,i))

    可惜这样做时间复杂度很高,无法承受。

    考虑剪枝。

    (ans(x)=sum_{i=1}^n(-1)^{i+1}f(x,i)),那么问题答案就是(ans(r)-ans(l-1))

    看看如何计算(ans(m))

    首先,我们发现当任意数量的幸运数字的(lcm)大于(m)的时候,就不存在对答案的贡献了。

    所以我们可以减去(lcm)已经大于(m)的情况。

    这样就省掉了大量无意义运算。

    这样能不能通过此题呢?事实证明不能。

    还有以下优化:

    1.降序排列(p),使得(lcm)可以更快地大于(m)

    然后你吸个氧气可能就过了。

    如果你还是过不了,我们可以减少(p)的长度。

    2.发现对于任意(p_j|p_i),(p_i)的倍数都是(p_j)的倍数。

    所以删去(p_i)不会影响答案。

    然后应该是铁定过了。

    评测记录(吸了氧气)

    所有优化

    只有2

    只有1的莫名WA掉了,提交记录就不放了。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int p[15]={0,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1};
    long long l,r,n,ln[1050],sz,ued[1050],ans;
    queue<long long>q;
    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?x*(y/gcd(x,y)):y;
    }
    bool P(long long x,long long y){
        return ((x<=1e9)||(y<=1e9));
    }
    bool cmp(long long x,long long y){
        return x>y;
    }
    void Getln(){
        long long x;
        q.push(6),q.push(8);
        while(!q.empty()){
            x=q.front(),q.pop();
            for(int i=1;i<=sz;++i)if(x%ln[i]==0)goto END;
            ln[++sz]=x;
            END:
            x*10+6<=r?(q.push(x*10+6),(x*10+8<=r?q.push(x*10+8),0:0)):0;
        }
    }
    void dfs(int x,int tt,long long lm){
        (x>sz&&lm)?ans+=p[tt]*(n/lm):0;
        if(x>sz||lm>n)return;
        dfs(x+1,tt,lm),P(lm,ln[x])?dfs(x+1,tt+1,lcm(lm,ln[x])),0:0;
    }
    long long Work(long long x){
        ans=0,n=x,dfs(1,0,0);
        return ans;
    }
    int main(){
        scanf("%lld%lld",&l,&r);
        Getln();
        sort(ln+1,ln+sz+1,cmp);
        printf("%lld",Work(r)-Work(l-1));
        return 0;
    }
    
  • 相关阅读:
    linux 运维必备150个命令
    CentOS 6.5 安装nginx 1.6.3
    centos 6.5 zabbix3.0.4 监控apache
    iOS更改ShareSDK默认的分享功能界面
    使用AFNetworking时, 控制器点击返回销毁了, 但还是会执行请求成功或失败的block, 导致野指针异常
    iOS性能优化
    'Invalid update: invalid number of rows in section xx. The number of rows contained in an existing section after the update (xxx)...
    iOS 改变UITextField中光标颜色
    使用ShareSDK完成Facebook第三方登录和Facebook分享时没办法跳转到Facebook应用
    [!] Unable to satisfy the following requirements:
  • 原文地址:https://www.cnblogs.com/xryjr233/p/BZOJ1853.html
Copyright © 2011-2022 走看看