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;
    }
    
  • 相关阅读:
    MQTT TLS 加密传输
    python多进程并发redis
    各种消息队列的特点
    mqtt异步publish方法
    Numpy API Analysis
    Karma install steps for unit test of Angular JS app
    reinstall bower command
    Simulate getter in JavaScript by valueOf and toString method
    How to: Raise and Consume Events
    获取对象的类型信息 (JavaScript)
  • 原文地址:https://www.cnblogs.com/mollnn/p/12295987.html
Copyright © 2011-2022 走看看