void solve(std::istream& in, std::ostream& out) {
		int n;
		in >> n;
		using Z = ZnConst<1000000007>;
		int mx = 2500001;
		vector<int> v(n);
		struct Info {
			int pos, ans;
			Z c;
		};
		vector<vector<Info>> infos(mx);
		//for (int i: range(mx)) { //initialize lazily
		//	infos[i].push_back({-1, 0, Z::rawValueOf(1)});
		//}
		struct PrefInfo {
			Z sum, sumcpos;
		};
		vector<vector<PrefInfo>> prefs(mx);
		//for (int i: range(mx)) {
		//	prefs[i].push_back({Z(), Z()});
		//	prefs[i].push_back({Z::rawValueOf(1), Z::valueOf(-1)});
		//}

		vector<pair<int, int>> gcds;
		for (int i: range(n)) {
			in >> v[i];
		}

		gcds.push_back({-1, -1});

		for (int i: range(n)) {
			vector<pair<int, int>> newgcd;
			newgcd.push_back({-1, -1});
			for (auto j = 1; j < gcds.size(); ++j) {
				auto g = gcds[j];
				g.first = gcd(g.first, v[i]);
				if (g.first == newgcd.back().first) {
					newgcd.back().second = g.second;
				} else {
					newgcd.emplace_back(g.first, g.second);
				}
			}
			newgcd.emplace_back(v[i], i);

			gcds = move(newgcd);

			for (int j = 1; j < gcds.size(); ++j) {
				int g = gcds[j].first;
				if (infos[g].empty()) { // fixing mempry problems
					infos[g].push_back({-1, 0, Z::rawValueOf(1)});
					prefs[g].push_back({Z(), Z()});
					prefs[g].push_back({Z::rawValueOf(1), Z::valueOf(-1)});
				}
				auto endofgood = std::partition_point(infos[g].begin(), infos[g].end(), [&](Info info) {
					return info.pos < gcds[j].second;
				}) - infos[g].begin();

				Info new_info = {i, -1, Z::valueOf(0)};
				new_info.ans = infos[g][endofgood - 1].ans + 1;
				auto start_of_same_answer = std::partition_point(infos[g].begin(), infos[g].end(), [&](Info info) {
					return info.ans < new_info.ans - 1;
				}) - infos[g].begin();
				auto center = std::partition_point(infos[g].begin(), infos[g].end(), [&](Info info) {
					return info.pos < gcds[j - 1].second;
				}) - infos[g].begin();

				if (center >= start_of_same_answer) {
					new_info.c += (prefs[g][center].sum - prefs[g][start_of_same_answer].sum) * (gcds[j].second - gcds[j - 1].second);
				}
				int st = (int) max(center, start_of_same_answer);
				new_info.c += gcds[j].second * (prefs[g][endofgood].sum - prefs[g][st].sum) -(prefs[g][endofgood].sumcpos - prefs[g][st].sumcpos);
				infos[g].push_back(new_info);
				prefs[g].push_back({prefs[g].back().sum + new_info.c, prefs[g].back().sumcpos + new_info.c * new_info.pos});
			}
		}

		int maxans = 0;
		for (int i: range(mx)) {
			if (!infos[i].empty()) {
				maxans = max(maxans, infos[i].back().ans);
			}
		}

		Z res;
		for (int i: range(mx)) {
			for (auto t: infos[i]) {
				if (t.ans == maxans) {
					res += t.c;
				}
			}
		}

		out << maxans << ' ' << res << "\n";
	}