TheAlmostLuckyNumbers TopCoder - 10420 容斥原理+奇加偶减

版权声明:布呗之路的守望者 https://blog.csdn.net/hypHuangYanPing/article/details/82228696
/**
链接:https://community.topcoder.com/stat?c=problem_statement&pm=10420
题意:lucky number :只包含数字4和7数字;
almostLuckyNumbers:能够被lucky number整除的数字
问[a,b]中存在多少个almostluckynumber;

分析:先预处理出所有的只含4和7的数字 去除冗余的情况后进行容斥;
遵循奇加偶减的性质 暴力容斥原理 枚举选出哪些数能够被ta们的lcm整除
剪枝小优化:可先枚举数字比较大的数字,再选择枚举数字比较小的数字;
这样的话,lcm可以很快的超出区间的范围 这样缩小搜索的深度;
此可作为模板记下;
时间复杂度2^k;
*/

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn=1e5+7;
bool vis[maxn];
vector<ll>a,b;
ll l,r,ans;

class TheAlmostLuckyNumbers{
public:
	void pre(ll sum){
		if(sum>r) return ;
		if(sum>0) a.push_back(sum);
		pre(sum*10+4);
		pre(sum*10+7);
	}
	ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
	void dfs(int step,int flag,ll sum){
		
		if(step==b.size()) { ans+=flag*(r/sum-(l-1)/sum);return ; }//记录的是不能够整除的情况
		dfs(step+1,flag,sum);
		ll tmp=sum/gcd(b[step],sum);
		if((double)b[step]*tmp<=r) dfs(step+1,-flag,b[step]*tmp);
	}
	ll count(ll p,ll q){
		l=p,r=q;
		pre(0);
		sort(a.begin(),a.end());
		for(int i=0;i<a.size();i++){//冗余
			if(!vis[i]) {
				for(int j=i+1;j<a.size();j++)
					if(a[j]%a[i]==0) vis[j]=1;
				b.push_back(a[i]);
			}
		}
		reverse(b.begin(),b.end());
		dfs(0,1,1);
		return (q-p+1)-ans;
	}
};

猜你喜欢

转载自blog.csdn.net/hypHuangYanPing/article/details/82228696
今日推荐