1. 程式人生 > 實用技巧 >上午小測1「木板」

上午小測1「木板」

上午小測1「木板」

題目大意

題幹

分析

簡單推論

老數學題了,直接開搞:

\[設 \;BE = x,CE = n - x, CF = y, \angle AEF = 90^{\circ} \]

\[\because \Delta ABE \sim \Delta ECF \]

\[\therefore \frac{AB}{BE} = \frac{EC}{CF} \]

\[\therefore \frac{n}{x} = \frac{n - x}{y} \]

\[\therefore y = \frac {nx-x^2}{n} = x - \frac{x^2}{n} \]

\[\because x\in \mathbb{Z}\;且\;y\in \mathbb{Z} \]

\[\therefore n|x^2 \]

\[設\;n=p_1^{a_1}\times p_2^{a_2}\times p_3^{a_3}\times \cdots p_i^{a_i}(p_i\in \mathbb{P}) \]

\[\therefore x_{min} = p_1^{\left \lceil \frac{a_1}{2} \right \rceil}\times p_2^{\left \lceil \frac{a_2}{2} \right \rceil}\times p_3^{\left \lceil \frac{a_3}{2} \right \rceil}\times \cdots \times p_i^{\left \lceil \frac{a_i}{2} \right \rceil}(p_i\in \mathbb{P}) \]

\[設\; k\in \mathbb{Z} \]

\[\because kx_{min} < n \]

\[\therefore k < \frac{n}{x_{min}} \]

\[易得\; ans = k - 1 \]


進一步計算

  • 如何求 \(x_{min}\)

會發現,每個質因子次冪是向上取整的,當次冪是奇數的時候,有一個 \(p_i\) 是必須選取的,剩下的選一半即可。

\[設\; n=2^3\times 3^2\times 5^1 \]

\[x_{min} = 2^2\times 3^1\times 5^1 \]

\[有\; 2^1\; 和\; 5^1\; 是必選的 \]

\[設\; i (i ^ 2\leq n\; 且\; i^2|n), b = 2^1\times 5^1 \]

\[\because i_{max} = 2^1\times 3^1 \]

\[\therefore b = \frac{n}{i^2_{max}} \]

\[\therefore x_{min} = i_{max}b = \frac{n}{i_{max}} \]

\[\because k < \frac{n}{x_{min}} \]

\[\therefore k < i_{max} \]

\[\because ans = k - 1 \]

\[\therefore ans = i_{max} - 1 \]

\[\therefore ans = ans\times 8(正方形,四個角,直角在兩邊) \]

\[證畢 \]

程式碼

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

#define int long long

using namespace std;

const int maxn = 1e5 + 50, INF = 0x3f3f3f3f;

inline int read () {
	register int x = 0, w = 1;
	register char ch = getchar ();
	for (; ch < '0' || ch > '9'; ch = getchar ()) if (ch == '-') w = -1;
	for (; ch >= '0' && ch <= '9'; ch = getchar ()) x = x * 10 + ch - '0';
	return x * w;
}

inline void write (register int x) {
	if (x / 10) write (x / 10);
	putchar (x % 10 + '0');
}

int n, ans;

signed main () {
	freopen ("tri.in", "r", stdin);
	freopen ("tri.out", "w", stdout);
	while (1) {
		n = read();
		if (n == 0) break;
		for (register int i = 1; i * i <= n; i ++) {
			if (n % (i * i) == 0) ans = (i - 1) * 8;
		}
		printf ("%lld\n", ans);
	}
	return 0;
}