• 【BZOJ3837】[PA2013]Filary


    【BZOJ3837】[PA2013]Filary

    题面

    darkbzoj

    题解

    考虑到模数为(2)时答案至少为(frac n2),这是我们答案的下界。

    那么我们对于任意的一个数,它们答案集合中的就概率至少为(frac 12)

    那么我们随机选出一个数,将这个数与其他数作差,那么将这些数分解质因数后出现次数最多的数的个数就是出现次数,而含有这个质因数的所有数的(gcd)就是这种情况。

    因为值域(leq 10^7),所以你把每个数最小的质因子筛出来就可以做到(log)的分解质因数了,注意特判差为零的情况。

    如果你不是太非随机十次左右就够了。

    代码

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm>
    #include <ctime> 
    using namespace std; 
    inline int gi() { 
        register int data = 0, w = 1; 
        register char ch = 0; 
        while (!isdigit(ch) && ch != '-') ch = getchar(); 
        if (ch == '-') w = -1, ch = getchar(); 
        while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
        return w * data; 
    } 
    const int MAX_N = 1e5 + 5; 
    const int MAX_V = 1e7 + 5, MAX = 1e7; 
    int prime[700000], minp[MAX_V], num; 
    void sieve() { 
    	for (int i = 2; i <= MAX; i++) { 
    		if (!minp[i]) prime[++num] = i, minp[i] = i; 
    		for (int j = 1; j <= num && i * prime[j] <= MAX; j++) { 
    			minp[i * prime[j]] = prime[j]; 
    			if (i % prime[j] == 0) break; 
    		} 
    	} 
    } 
    int N, a[MAX_N], Cnt[MAX_V], Gcd[MAX_V]; 
    pair<int, int> ans; 
    
    int main () { 
    #ifndef ONLINE_JUDGE 
        freopen("cpp.in", "r", stdin); 
    #endif 
    	srand(time(NULL)); 
    	sieve(); 
    	N = gi(); 
    	for (int i = 1; i <= N; i++) a[i] = gi(); 
    	for (int i = 1; i <= N; i++) if (a[i] & 1) ans.first++; 
    	ans.first = max(ans.first, N - ans.first), ans.second = 2; 
    	for (int T = 10; T--; ) { 
    		int pos = rand() % N + 1, ALL = 0; 
    		for (int i = 1; i <= N; i++) { 
    			int dlt = abs(a[pos] - a[i]), tmp = dlt; 
    			if (!dlt) ++ALL;
    			else { 
    				int lst = 0; 
    				while (tmp != 1) { 
    					if (minp[tmp] != lst) { 
    						Cnt[minp[tmp]]++; 
    						Gcd[minp[tmp]] = __gcd(dlt, Gcd[minp[tmp]]); 
    					} 
    					lst = minp[tmp], tmp /= minp[tmp]; 
    				} 
    			} 
    		}
    		for (int i = 1; i <= N; i++) { 
    			int dlt = abs(a[pos] - a[i]), tmp = dlt; 
    			if (!dlt) continue; 
    			else { 
    				int lst = 0; 
    				while (tmp != 1) { 
    					if (minp[tmp] != lst) { 
    						ans = max(ans, make_pair(ALL + Cnt[minp[tmp]], Gcd[minp[tmp]])); 
    						Cnt[minp[tmp]] = 0; 
    						Gcd[minp[tmp]] = 0; 
    					} 
    					lst = minp[tmp], tmp /= minp[tmp]; 
    				} 
    			} 
    		} 
    	} 
    	printf("%d %d
    ", ans.first, ans.second); 
    	return 0; 
    } 
    
  • 相关阅读:
    【转载】Android应用框架及常用工具类总结
    【Android】Android开发规范的一点小体会
    【Android】解决Android的ListView控件滚动时背景变黑
    【Android】侧边栏SlidingMenu
    【Android】解决RadioButton+FragmentPagerAdapter+Fragment切换页面数据加载的问题
    【Android】ListView动态视图显示不全
    Android编码规范
    【Android】两个日期相差几天和两个日期比较大小
    Linux基础之快照克隆、Xshell优化、Linux历史
    Android APP打包时,出错:"XXX" is not translated in "af" (Afrikaans), "am" (Amharic)
  • 原文地址:https://www.cnblogs.com/heyujun/p/11765273.html
Copyright © 2020-2023  润新知