bzoj1853[Scoi2010]幸运数字 容斥原理

题意:给你一个区间,问区间内有多少个数字内只包含6,8的数字和其倍数。

和2393巨像,所以也是容斥原理(好像很显然)。
只有6,8的数字有2000多个,然后互质的搞搞就只有10几个了,这就很zici。
问题是怎么样处理其倍数,我们搜索一下,记录当前遍历到第几个幸运数,选择了多少个幸运数,已选择的幸运数的lcm是多少。
明显,近似幸运数是幸运数的lcm。而且,一个数以及其倍数在l,r中出现的次数=r/x-(l-1)/x,这样子我们就可以容斥原理xjb统计统计就好。
注意lcm不能比r大,不然会炸ll,加个剪枝就好。
由于前天晚上改了半天不知道哪里挂了一怒之下对着oxer的代码来了一发= =

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+5;
int n,m;
typedef long long ll;
ll q[N],l,r;
int tot;
bool vis[N];
ll ans;
inline void dfs(ll x)
{
    if (x>r)return;
    if (x)q[++tot]=x;
    dfs(x*10+6),dfs(x*10+8);
}
bool cmp(ll a,ll b)
{
    return a>b;
}
ll gcd(ll a,ll b)
{
    if (a%b==0)return b;
    else return gcd(b,a%b);
}
inline void dfs1(int x,int d,ll lcm)
{
    if (x==tot)return;
    x++;
    dfs1(x,d,lcm);
    d++;
    if(vis[x])return;
    lcm=lcm*q[x]/gcd(lcm,q[x]);
    if (lcm<=0||lcm>r)return;
    if (d&1)ans+=r/lcm-(l-1)/lcm;
    else ans-=r/lcm-(l-1)/lcm;
    dfs1(x,d,lcm);
}
int main()
{
    scanf("%lld%lld",&l,&r);
    dfs(0);
    sort(q+1,q+tot+1,cmp);
    fo(i,1,tot)
        fo(j,i+1,tot)
        if (q[i]%q[j]==0)vis[i]=1;
    dfs1(0,0,1);
    printf("%lld\n",ans);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值