zoukankan      html  css  js  c++  java
  • 【LG2567】[SCOI2010]幸运数字

    【LG2567】[SCOI2010]幸运数字

    题面

    洛谷

    题目大意:

    问你区间([L,R](1leq Lleq Rleq 10^{10}))中有几个数是仅由(6,8)组成的数的倍数。

    题解

    首先考虑容斥。

    但是这种数字去掉有倍数关系的数还有(943)个,还是无法直接容斥。

    这时候可以借鉴一下(meet;in;the;middle)的方式进行处理。

    发现去掉前(20)个数后,我们剩下的数的倍数加起来只有(10^6)级别了,那么我们对于前面(20)个数的情况,我们直接容斥解决,后面的数字我们可以全部枚举出来然后排序去重。

    然后这样的话还有一个小问题,就是前后合并时可能会算重,这样的话直接枚举后面每个数然后判断一下是否是前面的数的倍数即可。

    复杂度经过分析其实还是可以接受的,就是常数有点大,你可以考虑开个(O2)或者(20 ightarrow 19)再用哈希表去重。

    代码

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm> 
    #include <vector> 
    using namespace std; 
    int tot; 
    unsigned long long L, R, t[3000000]; 
    bool vis[3000]; 
    vector<unsigned long long> num; 
    unsigned long long fac[1000]; 
    int siz; 
    void dfs(int x, unsigned long long res) { 
    	if (res <= R && res) num.push_back(res); 
    	if (x == tot + 1) return ; 
    	dfs(x + 1, res * 10 + 6); 
    	dfs(x + 1, res * 10 + 8); 
    } 
    long long solve() { 
    	long long ans = 0; 
    	for (register int s = 1, l = min(siz, 19); s < 1 << l; s++) { 
    		unsigned long long lcm = 0; int tt = 0; 
    		for (register int i = 0; i < l; i++) 
    			if (s >> i & 1) { 
    				if (lcm) lcm = lcm * fac[i] / __gcd(fac[i], lcm); 
    				else lcm = fac[i];
    				++tt; 
    			} 
    		ans += (tt & 1 ? 1 : -1) * (R / lcm - (L - 1) / lcm); 
    	} 
    	if (siz <= 19) return ans; 
    	tot = 0; 
    	for (int i = 19; i < siz; i++) 
    		for (unsigned long long j = R / fac[i] * fac[i]; j >= L; j -= fac[i]) 
    			t[++tot] = j; 
    	sort(&t[1], &t[tot + 1]); 
    	tot = unique(&t[1], &t[tot + 1]) - t - 1; 
    	for (int i = 1; i <= tot; i++)  { 
    		bool flag = 1; 
    		for (int j = 0; j < 19 && flag; j++) 
    			if (t[i] % fac[j] == 0) flag = 0; 
    		ans += flag; 
    	} 
    	return ans; 
    } 
    int main () { 
    #ifndef ONLINE_JUDGE 
        freopen("cpp.in", "r", stdin); 
    #endif 
    	cin >> L >> R; 
    	long long tmp = R; 
    	while (tmp) ++tot, tmp /= 10; 
    	dfs(1, 0); 
    	sort(num.begin(), num.end()); 
    	for (int i = 0; i < (int)num.size(); i++) { 
    		if (vis[i]) continue; 
    		fac[siz++] = num[i]; 
    		for (int j = i + 1; j < (int)num.size(); j++) 
    			if (num[j] % num[i] == 0) vis[j] = 1; 
    	} 
    	printf("%lld
    ", solve()); 
        return 0; 
    } 
    
  • 相关阅读:
    Html5实现iPhone开机界面
    Html5游戏开发-145行代码完成一个RPG小Demo
    HTML5开源RPG游戏引擎lufylegendRPG 1.0.0发布
    如何制作一款HTML5 RPG游戏引擎——第五篇,人物&人物特效
    如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话
    如何制作一款HTML5 RPG游戏引擎——第三篇,利用幕布切换场景
    html5游戏开发-零基础开发《圣诞老人送礼物》小游戏
    如何制作一款HTML5 RPG游戏引擎——第二篇,烟雨+飞雪效果
    如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现
    读CopyOnWriteArrayList有感
  • 原文地址:https://www.cnblogs.com/heyujun/p/11765165.html
Copyright © 2011-2022 走看看