はまやんはまやんはまやん

hamayanhamayan's blog

Exponential notation [Codeforces 教育 14 : C]

問題

http://codeforces.com/contest/691/problem/C

正の小数値の文字列 x が与えられる。
これを x=a*10^b かつ 1 <= a < 10 となるように変形し、"aEb"の形で出力する。
b == 0 ならば "a" でよく、aが小数ではなく、整数の場合はカンマはいらない。

x <= 10^6

考察

1. この問題は考察というより、実装をどうやるかみたいな所がある
2. 考察書くの難しい

3. カンマがない場合 -> 場合分けも面倒なので、一番最後にカンマをつけて処理する

4. まず、カンマから順に左右に0以外が来る最大距離を求めておく
5. これにより、無駄な0を省ける

6. あとは、先頭が0にならないようにうまくやって終わり
7. カンマより左が0だけだった場合のために、右で最初に0以外が来る箇所をメモしておくとよい

8. サンプル4が親切なのでそれだけ何とかする

実装

http://codeforces.com/contest/691/submission/19099835

#define rrep(i,a,b) for(int i=a;i>=b;i--)
string x;
//-----------------------------------------------------------------
pair<string, int> solve() {
	int c = x.find(".");
	if (c == string::npos) {
		c = x.length();
		x += ".";
	}

	int n = x.length();

	int l = c;
	rrep(i, c, 0) if (x[i] != '0') l = i;
	int r = c;
	rep(i, c, n) if (x[i] != '0') r = i;

	if (l == c) {
		int m = c;
		rep(i, c + 1, n) if (x[i] != '0') {
			m = i;
			break;
		}

		return make_pair(x.substr(m, r - m + 1), c - m);
	}

	string ans = x.substr(l, c - l) + x.substr(c + 1, r - c);
	int zero = -1;
	rrep(i, ans.length() - 1, 0) {
		if (ans[i] == '0')
			zero = i;
		else
			break;
	}

	if (zero < 0) return make_pair(ans, c - l - 1);
	return make_pair(ans.substr(0, zero), c - l - 1);
}
//-----------------------------------------------------------------
int main() {
	cin >> x;
	auto ans = solve();

	rep(i, 0, ans.first.length()) {
		if (i != 1)
			printf("%c", ans.first[i]);
		else
			printf(".%c", ans.first[i]);
	}
	if (ans.second) printf("E%d", ans.second);
	printf("\n");
}