bzoj1853 [Scoi2010]幸运数字

网友投稿 786 2022-08-29

bzoj1853 [Scoi2010]幸运数字

bzoj1853 [Scoi2010]幸运数字

​​ Description 在中国,很多人都把6和8视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字6和8的那些号码,比如68,666,888都是“幸运号码”!但是这种“幸运号码”总是太少了,比如在[1,100]的区间内就只有6个(6,8,66,68,86,88),于是他又定义了一种“近似幸运号码”。lxhgww规定,凡是“幸运号码”的倍数都是“近似幸运号码”,当然,任何的“幸运号码”也都是“近似幸运号码”,比如12,16,666都是“近似幸运号码”。 现在lxhgww想知道在一段闭区间[a, b]内,“近似幸运号码”的个数。 Input 输入数据是一行,包括2个数字a和b Output 输出数据是一行,包括1个数字,表示在闭区间[a, b]内“近似幸运号码”的个数 Sample Input 【样例输入1】 1 10 【样例输入2】 1234 4321 Sample Output 【样例输出1】 2 【样例输出2】 809 HINT 【数据范围】 对于30%的数据,保证1 < =a < =b < =1000000 对于100%的数据,保证1 < =a < =b < =10000000000

Source Day1

可以发现其实就是 先搜索出所有的数 然后找他们的倍数即可

我们发现两两的lcm被多算了 然后减去 又发现三个的lcm多减了 所以加上

就这样 这题数据比较强 需要剪枝 就是double 那个乘起来大于右边界的时候结束即可

注意需要将原搜索序列翻转 效果更好

#include#define ll long longusing namespace std;const int N=1e5+10;ll a[N],l,r,ans;bool vis[N];int m,n;inline void init(int x,ll v){ if (v>r) return;if (x) a[++m]=v; init(x+1,v*10+6);init(x+1,v*10+8);}inline ll gcd(ll x,ll y){ return !y?x:gcd(y,x%y);}inline void dfs(int x,int nm,ll v){ if (x>n){ if(v==1) return;int op=nm&1?1:-1; ans+=r/v*op;ans-=(l-1)/v*op;return; }dfs(x+1,nm,v); ll g=v/gcd(a[x],v); if((double)g*a[x]<=r) dfs(x+1,nm+1,g*a[x]);}int main(){ //freopen("bzoj1853.in","r",stdin); scanf("%lld%lld",&l,&r); init(0,0);sort(a+1,a+m+1); for (int i=1;i<=m;++i){ if (vis[i]) continue; for (int j=i+1;j<=m;++j) if (a[j]%a[i]==0) vis[j]=1; a[++n]=a[i]; }reverse(a+1,a+n+1); dfs(1,0,1);printf("%lld\n",ans); return 0;}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:php+redis实现消息队列(thinkphp redis队列)
下一篇:NOI2018 模拟 T2
相关文章

 发表评论

暂时没有评论,来抢沙发吧~