卧薪尝胆,厚积薄发。
SCOI2010 幸运数字
Date: Wed Aug 01 15:31:52 CST 2018
In Category:
NoCategory
Description:
求
$[l,r]$
中是只含
$6$
和
$8$
的数的倍数的数的个数。
$1\le l\le r \le 10^{10}$
Solution:
先预处理出只由
$6$
和
$8$
组成的数,然后去掉所有一个数是另一个数的倍数,然后
$dfs$
容斥即可,注意为了防止爆
$long\ long$
要在中途转一下
$double$
判断。注意每次用
$lcm$
更新。还要将所有数倒序排序使得
$lcm$
能更快突破上界。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef unsigned long long ll;
ll l,r;
ll tot = 0;
ll s[2050];
bool tag[2050];
ll a[2050],siz = 0;
void pre(ll k)
{
if(k > r)return;
if(k > 0)s[++tot] = k;
pre(k * 10 + 6);
pre(k * 10 + 8);
return;
}
inline ll gcd(ll a,ll b){return (b == 0 ? a : gcd(b,a % b));}
inline ll lcm(ll a,ll b){return a / gcd(a,b) * b;}
ll res;
void calc(int pos,ll bord,ll cur,ll tag)
{
if(cur > bord)return;
if(pos == siz + 1)
{
res += tag * (bord / cur);
return;
}
calc(pos + 1,bord,cur,tag);
if((double)cur / (double)gcd(cur,a[pos]) * (double)a[pos] <= (double)bord)calc(pos + 1,bord,lcm(cur,a[pos]),-tag);
return;
}
inline ll work(ll k){if(k < 6)return 0;res = 0;calc(1,k,1,1);return k - res;}
bool cmp_rev(ll a,ll b){return a > b;}
int main()
{
scanf("%lld%lld",&l,&r);
pre(0);
for(register ll i = 1;i <= tot;++i)tag[i] = true;
sort(s + 1,s + 1 + tot);
for(register ll i = 1;i <= tot;++i)
{
if(tag[i])a[++siz] = s[i];
else continue;
for(register ll j = i + 1;j <= tot;++j)
{
if(s[j] % s[i] == 0)tag[j] = false;
}
}
sort(a + 1,a + 1 + siz,cmp_rev);//!!!!!
printf("%lld\n",work(r) - work(l - 1));
return 0;
}
In tag:
数学-容斥原理
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡