[Scoi2010] 幸运数字

42 篇文章 0 订阅
3 篇文章 0 订阅

题目描述:

雾。

题目分析:

先预处理出仅含6或8的数
然后用容斥原理求倍数
要从大到小搜,可以减少递归层数

题目链接:

Luogu 2567
BZOJ 1853

Ac 代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
const double eps=1e-3;
ll a[3000],l,r,ans;
bool vis[3000];
int cnt;
void pre(ll now)
{
    if(now>r) return;
    a[++cnt]=now;
    pre(now*10+6),pre(now*10+8);
}
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
void dfs(int now,int num,ll x)
{
    if(now>cnt)
    {
        //printf("%d %d %lld\n",now,num,x);
        if(num%2) ans+=(r/x-(l-1)/x);
        else if(num) ans-=(r/x-(l-1)/x);
        return;
    }
    ll tmp=x/gcd(x,a[now]);
    dfs(now+1,num,x);
    if((double)a[now]*tmp<=r+eps)
     dfs(now+1,num+1,tmp*a[now]);
}
inline bool comp(ll x,ll y){return x>y;}
int main()
{
    scanf("%lld%lld",&l,&r);
    pre(6),pre(8);
    std::sort(a+1,a+cnt+1,comp);
    for(int i=cnt;i>=1;i--)
     if(!vis[i])
      for(int j=i-1;j>=1;j--)
      if(!(a[j]%a[i]))
       vis[j]=1;

    int tmp=0;
    for(int i=1;i<=cnt;i++)
     if(!vis[i]) a[++tmp]=a[i];
    cnt=tmp;
    dfs(1,0,1);
    printf("%lld\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值