zoukankan      html  css  js  c++  java
  • 反素数(高合成数?)

    起源

    我在做某题时,想到一个问题,在(1)(100000)中,哪个数拥有最多的因子?
    在uoj的群问了一下,感谢vfleaking给了我一个完美答案

    传送门

    前一千个反素数
    一道求反素数的题,让我来贴个代码,不过写得有点丑,用的是这位大牛的搜索+剪枝方法Orz。

    为了防止百度空间挂掉,这里简单复述一下:

    (p_i)为第(i)个素数,比如(p_1=2,p_2=3,p_3=5)
    (q_i)为第(i)个素数的指数。

    因子个数为((q_1+1)(q_2+1)(q_3+1) ...)

    剪枝一

    [q_1 geq q_2 geq q_3 geq ... ]

    证明:
    假如有(q_i < q_{i+1}),那么令(q_i)加一,(q_{i+1})减一,答案更优。

    剪枝二

    对于(q_i(i>1)),令(K)为使(2^K>p_i)的最小整数。
    有$2{q_1}{p_i}{q_i} > 2^{q_1 + K - 1} {p_i}^{q_i-1} (, 如果)q_i(比)q_i-1(优,那么)(q_1+1)(q_i+1)>(q_1+K)q_i(, 即)q_i < frac {q_1+1} {K-1}(。这样我们就找到了)q_i$的上界。

    剪枝三

    对于(q_i(i>1)),令(K)为使(2^K>p_i)的最小整数。
    有$2^{q_1} {p_i}^{q_i} > 2^{q_1 - K}{p_i}^{q_i+1} (, 如果)q_i(比)q_i+1(优,那么)(q_1+1)(q_i+1)>(q_1-K+1)(q_i+2)(, 即)q_i > frac {q_1-2K+1} {K}(。这样我们就找到了)q_i$的下界。

    剪枝四

    (K)为满足(2^K > p_m)的最小整数,其中(p_m)(q_m)一定为(0)的最小数。
    (2^{q_1}>2^{q_1-K}p_m)
    前者必然比后者优,所以(q_1+1>2(q_1-K+1)),即(q_1<2K),这样,我们得到了(q_1)的上界。

    打表代码:

    #include <cstdio>
    #include <math.h>
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const int MAXDIGHT = 100;
    #include "GNum.h" //高精度的库,这里不贴了
    
    int main() {
    	static int fac[1000000], a[1000000];
    	int cnt = 0;
    	memset(fac, -1, sizeof(fac));
    
    	static GNum x;
    	x.A[0] = 1;
    	cout << "const prime[54] = {";
    
    	for (int i = 2; i <100000; i ++) {
    		if (fac[i] == -1) {
    			cout << i;
    			a[cnt ++] = i;
    			fac[i] = i;
    			x.mul(i);
    			if (x.len > 25) break;
    			cout << ',';
    		}
    		for (int j = 0; j < cnt && a[j] <= fac[i]; j ++) {
    			fac[i * a[j]] = a[j];
    		}
    	}
    	cout << "};
    ";
    
    	cout << "const limitUpper[16][" << cnt << "] = {";
    	for (int q1 = 0; q1 < 16; q1 ++) {
    		if (q1) for (int i = 0; i < 28; i ++) cout << ' ';
    		cout << "{";
    		for (int i = 0; i < cnt; i ++) {
    			int p = a[i];
    			int k = ceil(log(p) / log(2));
    			int ans = ceil((double) (q1 + 1) / (k -1)) ;
    			if (i == 0) cout << 16;
    			else {
    				if (q1 && i) cout << ans;
    				else cout << "0";
    			}
    			if (i == cnt-1) cout << "}";
    			else cout << ',';
    		}
    		if (q1 == 16-1) cout << "};
    ";
    		else cout << ",
    ";
    	}
    
    	cout << "const limitLower[16][" << cnt << "] = {";
    	for (int q1 = 0; q1 < 16; q1 ++) {
    		if (q1) for (int i = 0; i < 28; i ++) cout << ' ';
    		cout << "{";
    		for (int i = 0; i < cnt; i ++) {
    			int p = a[i];
    			int k = ceil(log(p) / log(2));
    			int ans = ceil((double) (q1 + 1 - 2* k) / k) ;
    			if ((q1 && i) && ans > 0) cout << ans;
    			else cout << "0";
    			if (i == cnt-1) cout << "}";
    			else cout << ',';
    		}
    		if (q1 == 16-1) cout << "};
    ";
    		else cout << ",
    ";
    	}
    
    
    	return 0;
    }
    

    提交代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    const int DIG = 10000;
    const int MAXDIGHT = 29;
    
    const int prime[54] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251};
    const int limitUpper[16][54] = {{16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{16,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    	{16,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    	{16,4,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    	{16,5,3,3,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    	{16,6,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    	{16,7,4,4,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    	{16,8,4,4,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
    	{16,9,5,5,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
    	{16,10,5,5,4,4,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
    	{16,11,6,6,4,4,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
    	{16,12,6,6,4,4,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
    	{16,13,7,7,5,5,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
    	{16,14,7,7,5,5,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
    	{16,15,8,8,5,5,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
    	{16,16,8,8,6,6,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}};
    const int limitLower[16][54] = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,3,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,3,2,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,4,2,2,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,4,2,2,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,5,3,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,5,3,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,6,3,3,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    	{0,6,4,4,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
    
    struct GNum{
    	int A[MAXDIGHT], len;
    
    	GNum() {
    		len = 1;
    		A[0] = 0;
    	}
    
    	void input() {
    		static int buf[1000];
    		len = 0;
    		int* ch = buf; 
    		*(ch ++) = '#';
    		do *ch = getchar(); while (*ch < '0' || *ch > '9');
    		do *(++ ch) = getchar(); while (*ch >= '0' && *ch <= '9');
    		ch --;
    
    		int cnt = 0, num = 0, s = 1;
    		while (*ch != '#') {
    			num += s * (*ch - 48);
    			cnt ++;
    			s *= 10;
    			if (cnt == 4) {
    				cnt = 0;
    				A[len ++] = num;
    				num = 0, s = 1;
    			}
    			ch --;
    		}
    		if (cnt) A[len ++] = num;
    	}
    
    	void output() {
    		printf("%d", A[len - 1]);
    		for (int i = len - 2; i >= 0; i --)
    			printf("%04d", A[i]);
    	}
    
    	void mul(const int &x) {
    		if (x == 0) {
    			len = 1;
    			A[0] = 0;
    			return;
    		}
    		for (int i = 0; i < len; i ++) {
    			A[i] *= x;
    		}
    		for (int i = 0; i + 1 < len; i ++) {
    			A[i + 1] += A[i] / DIG;
    			A[i] %= DIG;
    		}
    		while (A[len - 1] >= DIG) {
    			A[len] = A[len - 1] / DIG;
    			A[len - 1] %= DIG;
    			len ++;
    		}
    	}
    };
    
    GNum upper;
    
    bool check(GNum &a, GNum &upper) {
    	if (a.len != upper.len) return a.len < upper.len;
    	for (int i = a.len - 1; i >= 0; i --) {
    		if (a.A[i] != upper.A[i]) return a.A[i] < upper.A[i];
    	}
    	return true;
    }
    
    long long ans;
    GNum num[54], ansNum;
    
    void copyNum(GNum &des, GNum &src) {
    	des.len = src.len;
    	for (int i = 0; i < src.len; i ++) 
    		des.A[i] = src.A[i];
    }
    
    void dfs(int depth, long long comb, int used, int p1) {
    	GNum &x = num[depth];
    	if (check(x, upper))
    		if (comb > ans || (comb == ans && check(x, ansNum))) ans = comb, copyNum(ansNum, x);
    		else;
    	else return;
    	GNum &y = num[depth + 1];
    	copyNum(y, x);
    	if (! used) return;
    
    	int L = limitLower[p1][depth];
    	int R = min(used + 1, limitUpper[p1][depth]);
    	for (int i = 0; i < L; i ++) y.mul(prime[depth]);
    
    	for (int i = L; i < R; i ++) {
    		dfs(depth + 1, comb * (i + 1), i, p1);
    		y.mul(prime[depth]);
    	}
    }
    
    int main() {
    	upper.input();
    	/*
    	upper.output();
    	printf("
    ");
    	*/
    	num[1].A[0] = 1;
    	for (int i = 0; i < 16; i ++) {
    		dfs(1, i + 1, i, i);
    		num[1].mul(2);
    	}
    	ansNum.output();
    	printf("
    ");
    	return 0;
    }
    
  • 相关阅读:
    转(一万小时定律的文章): const 与 readonly区别...
    项目中报错邮件方法
    Windows Phone(一) 正式开发之前的准备资料(主要注册开发者账号,手机解锁,激活码,程序部署)
    转(ASP.NET页面缓存)
    部署XAP时,部署工具提示部署无效,求解决!
    jQuery 1
    DOMform
    jQuery 2 一些常用的函数
    jQuery 6 层次选择器
    jQuery 3 对象转换
  • 原文地址:https://www.cnblogs.com/wangck/p/4298919.html
Copyright © 2011-2022 走看看