zoukankan      html  css  js  c++  java
  • bzoj1853-大包子的幸运数字

    题意

    称只含有 6 和 8 的数字为幸运数字。称幸运数字的倍数为类幸运数字。求 ([l,r]) 中有多少个类幸运数字。(1le l,rle 10^{10})

    分析

    幸运数字最多有 (2^{11}-2) 个,先全部找出来,有倍数关系的留下最小的那个。容斥显然,关键是怎么写。

    暴力dfs最小公倍数。

    两个优化。第一,如果当前的最小公倍数已经大于 (r) 那么就退出。第二,所有幸运数字从大到小排序,这样不合法情况不用到最后才退出,大大降低时间。

    复杂度:(O(2^len(r)+不知道))

    代码

    以后写暴力要把不合法的条件在递归进去之前判掉。

    最小公倍数会爆 long long ,所以需要用double来跟 (r) 比较。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long giant;
    const int maxl=2100;
    giant l,r,b[maxl],a[maxl],ans=0;
    bool no[maxl];
    int m=0,n=0;
    giant gcd(giant x,giant y) {
    	return y?gcd(y,x%y):x;
    }
    void calc(int now,giant x,bool f) {
    	if (now>n) {
    		giant tmp=r/x-(l-1)/x;
    		if (x!=1) ans+=(f?tmp:-tmp);
    		return;
    	}
    	calc(now+1,x,f);
    	giant tmp=(x/gcd(a[now],x));
    	if ((double)tmp*a[now]<=r) calc(now+1,tmp*a[now],f^true);
    }
    void get(giant now) {
    	if (now>r) return;
    	if (now) b[++m]=now;
    	get(now*10+6);
    	get(now*10+8);
    }
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("test.in","r",stdin);
    #endif
    	cin>>l>>r;
    	get(0);
    	sort(b+1,b+m+1);
    	for (int i=1;i<=m;++i) if (!no[i]) {
    		a[++n]=b[i];
    		for (int j=i+1;j<=m;++j) if (b[j]%b[i]==0) no[j]=true;
    	}
    	reverse(a+1,a+n+1);
    	calc(1,1,false);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    android作业10.21
    安卓10.7作业
    安卓9.30
    9.23作业
    9.17安卓作业
    6.12作业
    5.29作业
    5.28上机作业
    leetcode 219
    策略模式
  • 原文地址:https://www.cnblogs.com/owenyu/p/7375664.html
Copyright © 2011-2022 走看看