zoukankan      html  css  js  c++  java
  • [HNOI2001] 求正整数

    对于任意输入的正整数n,请编程求出具有n个不同因子的最小正整数m。

    Solution

    (乍一看很简单却搞了好久?我真是太菜了)

    根据因子个数计算公式

    (m = prod p_i^{q_i}), 则 (n = prod (q_i + 1))

    (f[i][j]) 为只包含前 (j) 个质因数,因子个数为 (i) 的最小的数

    转移类似背包: (f[i][j]=min_{k|i} (f[i/k][j-1] cdot p_j^{k-1}))

    这样直接做是 (O(n sqrt n log n)) ,考虑到需要枚举的 (i) 有且仅有 (n) 的因数,而约数个数的一个宽上界是 (O(sqrt n)),复杂度就压缩到了 (O(n log n))

    使用高精度直接 dp 可能会复杂度爆炸,所以我们对数一下

    #include <bits/stdc++.h>
    using namespace std;
    
    struct Biguint {
    	int a[100005], len;
    
    	Biguint() {
    		memset(a, 0, sizeof a);
    		len = 0;
    	}
    
    	void read() {
    		string str;
    		cin >> str;
    		memset(a, 0, sizeof a);
    		len = str.length();
    		for (int i = 0; i < str.size(); i++)
    			a[i] = str[str.length() - i - 1] - '0';
    	}
    
    	void print() {
    		for (int i = len - 1; i >= 0; i--) {
    			cout << a[i];
    		}
    	}
    
    	bool operator < (const Biguint& obj) {
    		const int* b = obj.a;
    		if (this->len == obj.len) {
    			for (int i = len - 1; i>=0; --i)
    				if (a[i] != b[i]) return a[i] < b[i];
    			return false;
    		}
    		else return this->len < obj.len;
    	}
    
    	bool operator > (const Biguint& obj) {
    		const int* b = obj.a;
    		if (this->len == obj.len) {
    			for (int i = len - 1; i>=0; --i)
    				if (a[i] != b[i]) return a[i] > b[i];
    			return false;
    		}
    		else return this->len > obj.len;
    	}
    
    	bool operator != (const Biguint& obj) {
    		return (*this < obj) | (*this > obj);
    	}
    
    	bool operator == (const Biguint& obj) {
    		return !((*this < obj) | (*this > obj));
    	}
    
    	bool operator <= (const Biguint& obj) {
    		return (*this) < obj || (*this) == obj;
    	}
    
    	bool operator >= (const Biguint& obj) {
    		return (*this) > obj || (*this) == obj;
    	}
    
    	Biguint operator += (const Biguint& obj) {
    		const int* b = obj.a;
    		if (obj.len > len) len = obj.len;
    		for (int i = 0; i < len; i++) {
    			a[i] += b[i];
    			if (a[i] >= 10) a[i + 1] += a[i] / 10, a[i] %= 10;
    		}
    		if (a[len]) ++len;
    		while (a[len - 1] >= 10)
    			a[len] += a[len - 1] / 10, a[len - 1] %= 10, ++len;
    		return *this;
    	}
    
    	Biguint operator + (const Biguint& obj) {
    		Biguint ret;
    		ret += *this;
    		ret += obj;
    		return ret;
    	}
    
    	Biguint operator -= (const Biguint& obj) {
    		const int* b = obj.a;
    		for (int i = 0; i < len; i++) {
    			a[i] -= b[i];
    			if (a[i] < 0) a[i + 1]--, a[i] += 10;
    		}
    		while (a[len - 1] == 0 && len > 0) --len;
    		return *this;
    	}
    
    	Biguint operator -(const Biguint& obj) {
    		Biguint ret;
    		ret += *this;
    		ret -= obj;
    		return ret;
    	}
    
    	Biguint operator *= (int b) {
    		for (int i = 0; i < len; i++)
    			a[i] *= b;
    		for (int i = 0; i < len; i++)
    			a[i + 1] += a[i] / 10, a[i] %= 10;
    		++len;
    		while (a[len - 1] >= 10)
    			a[len] += a[len - 1] / 10, a[len - 1] %= 10, ++len;
    		while (a[len - 1] == 0 && len > 0) --len;
    		return *this;
    	}
    
    	Biguint operator * (int b) {
    		Biguint ret;
    		ret = *this;
    		ret *= b;
    		return ret;
    	}
    
    	Biguint operator * (const Biguint& obj) {
    		const int* b = obj.a;
    		Biguint ret;
    		for (int i = 0; i < len; i++)
    			for (int j = 0; j < obj.len; j++)
    				ret.a[i + j] += a[i] * b[j];
    		for (int i = 0; i < len + obj.len; i++)
    			ret.a[i + 1] += ret.a[i] / 10, ret.a[i] %= 10;
    		ret.len = len + obj.len;
    		++ret.len;
    		while (ret.a[ret.len - 1])
    			ret.a[ret.len] += ret.a[ret.len - 1] / 10, ret.a[ret.len - 1] %= 10, ++ret.len;
    		while (ret.a[ret.len - 1] == 0 && ret.len > 0) --ret.len;
    		return ret;
    	}
    
    };
    
    ostream& operator << (ostream& os, Biguint num)
    {
    	for (int i = num.len - 1; i >= 0; --i)
    		os << num.a[i];
    	if (num.len == 0) os << "0";
    	return os;
    }
    
    istream& operator >> (istream& is, Biguint& num)
    {
    	string str;
    	is >> str;
    	memset(num.a, 0, sizeof num.a);
    	num.len = str.length();
    	for (int i = 0; i < str.length(); i++)
    		num.a[i] = str[str.length() - i - 1] - '0';
    	return is;
    }
    
    
    const int N = 500005;
    const int p[21] = {0, 2,  3,  5,  7, 11, 13, 17, 19, 23, 29,
        31, 37, 41, 43, 47, 53, 59, 61, 67, 71};
    int n,g[50005][21],h[50005][21],ii[50005],top;
    double lp[21]={},f[50005][21];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<=n;i++) if(n%i==0) ii[++top]=i;
        for(int i=1;i<=20;i++) lp[i]=log(p[i]);
        for(int i=0;i<=50000;i++) for(int j=0;j<=20;j++) f[i][j]=1e9;
        f[1][0]=1;
        for(int _i=2;_i<=top;_i++) {
            int i=ii[_i];
            int sq=sqrt(i);
            for(int j=1;j<=20;j++) {
                for(int k=1;k<=sq;k++) {
                    if(i%k==0) {
                        if(f[i][j]>f[i/k][j-1]+(k-1)*lp[j]) {
                            f[i][j]=f[i/k][j-1]+(k-1)*lp[j];
                            g[i][j]=i/k;
                            h[i][j]=k-1;
                        }
                    }
                }
                for(int u=1;u<=sq;u++) {
                    int k=i/u;
                    if(i%k==0) {
                        if(f[i][j]>f[i/k][j-1]+(k-1)*lp[j]) {
                            f[i][j]=f[i/k][j-1]+(k-1)*lp[j];
                            g[i][j]=i/k;
                            h[i][j]=k-1;
                        }
                    }
                }
            }
        }
        int pos=n;
        Biguint ans;
        ans.len=1;
        ans.a[0]=1;
        for(int j=20;j;--j) {
            int i=pos;
            for(int k=1;k<=h[i][j];k++) ans*=p[j];
            pos=g[i][j];
        }
        cout<<ans;
    }
    
  • 相关阅读:
    linux删除目录的命令
    Windows XP下git通过代理下载android代码
    白话算法希尔排序
    操作系统——存储技术
    如何理解Linus Torvalds的“什么才是优秀程序员”的话
    程序员自我修养读书随笔——目标文件
    面试求职:大数据处理总结
    持久化与Session定义
    java中byte转换int时为何与0xff进行与运算
    OSI七层相关协议
  • 原文地址:https://www.cnblogs.com/mollnn/p/12295987.html
Copyright © 2011-2022 走看看