Cod sursa(job #1757203)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 14 septembrie 2016 17:53:05
Problema NumMst Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.97 kb
#include <fstream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;

int main() {
	ifstream cin("nummst.in");
	ofstream cout("nummst.out");
	cin.tie(0);
	ios_base::sync_with_stdio(0);

	int N; cin >> N;

	int lowestDivisor = 2;
	while(N != N / lowestDivisor * lowestDivisor) {
		lowestDivisor = (lowestDivisor + 2 - (lowestDivisor == 2));
	}

	// gcd = N / lowestDivisor
	// scriu lowestDivisor ca suma de numere prime intre ele ale caror produs sa fie maximal

	if(lowestDivisor < 5) {
		cout << N / lowestDivisor << ' ' << N - N / lowestDivisor << '\n';
		return 0;
	}

	vector<int> primes;
	vector<bool> mark(lowestDivisor + 1, false);
	for(int i = 2; i <= lowestDivisor; ++i) {
		if(!mark[i]) {
			primes.push_back(i);
			for(int j = i * i; j <= lowestDivisor; j += i)
				mark[j] = true;
		}
	}

	vector<double> dp[2];
	dp[0].resize(lowestDivisor + 1);
	fill(dp[0].begin(), dp[0].end(), .0);
	dp[1].resize(lowestDivisor + 1);
	vector<vector<int>> from(primes.size() + 1, vector<int>(lowestDivisor + 1, 0));
	for(int ptr = 1, i = 1; i <= (int)primes.size(); ++i, ptr ^= 1) {
		const double lgPrime = log(primes[i - 1]);
		fill(dp[ptr].begin(), dp[ptr].end(), .0);
		for(int j = 0; j + primes[i - 1] <= lowestDivisor; ++j) {
			for(int step = 1, k = primes[i - 1]; j + k <= lowestDivisor; k *= primes[i - 1], step++) {
				if(dp[ptr][k + j] < dp[ptr ^ 1][j] + lgPrime * step) {
					dp[ptr][k + j] = dp[ptr ^ 1][j] + lgPrime * step;
					from[i][k + j] = k;
				}
			}
		}
		for(int j = 0; j <= lowestDivisor; ++j) {
			if(dp[ptr][j] < dp[ptr ^ 1][j]) {
				dp[ptr][j] = dp[ptr ^ 1][j];
				from[i][j] = 0;
			}
		}
	}

	int state = lowestDivisor;
	for(int i = (int)primes.size(); i >= 1; --i) {
		if(from[i][state] != 0) {
			cout << from[i][state] * N / lowestDivisor << ' ';
			state -= from[i][state];
		}
	}
	while(state > 0) {
		cout << N / lowestDivisor << ' ';
		state--;
	}
	cout << '\n';

	return 0;
}