111. Very simple problem
Time Limit: 0.25 sec, Memory Limit: 1 MB
You are given natural number X. Find such maximum integer number that it square
is not greater than X.
Input
Input file contains number X (1 ≤ X ≤ 10^1000).
Output
Write answer in output file.
Sample Input
16
Sample Output
4
题意很简单,就是求一个可能多达1000位的正整数 X 的平方根的整数部分。
初学 JAVA ,用 JAVA 的 BigInteger 类来实现牛顿迭代求平方根 (很多库函数不知道,靠自己来写咯)。
import
java.math.
*
;
import java.io. * ;
public class Solution {
// 将字符串转为正整数
static int str2int (String str) // 0 <= the integer <= 2 ^ 31 -1
{
int ret = 0;
for (int i = 0, j = str.length (); i < j; i ++)
{
ret = ret * 10 + str.charAt(i) - '0';
}
return ret;
}
// 将正整数转为字符串
static String int2str (int i) // 0 <= i <= 2 ^ 31 -1
{
StringBuffer sb = new StringBuffer ("0000000000");
int digit = 0;
if (i == 0)
{
return "0";
}
while (i > 0)
{
digit ++;
int low = i % 10;
i /= 10;
sb.setCharAt (10 - digit, (char)(sb.charAt(10 - digit) + low));
}
return sb.substring(10 - digit);
}
// 求正整数的平方根的整数部分 (这个是抄自 Hacker's Delight 一书的)
static int isqrt (int x) // 0 <= x <= 2 ^ 31 -1
{
int b, m = 0x40000000, y = 0;
while (m != 0)
{
b = y | m;
y >>= 1;
if (x >=b)
{
x -= b;
y |= m;
}
m >>= 2;
}
return y;
}
public static void main (String[] args) throws IOException
{
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
String str = br.readLine ();
BigInteger bi [] = new BigInteger [3];
bi [0] = new BigInteger (str); // bi [0] 保存需要求平方根的数 X
int len = str.length ();
// 如果 X 小于 1000000000,那么直接求平方根的整数部分
if (len < 10)
{
System.out.println (isqrt (str2int (str)));
return;
}
// 如果 X 的位数是奇数,high 等于 X 的最高位,否则等于最高两位
int high = str.charAt(0) - '0';
if (len % 2 == 0)
{
high = high * 10 + str.charAt(1) - '0';
}
// 将 high 的平方根的整数部分加上 1 之后乘以 10^((len - 1) / 2)
// 乘积不小于 X 的平方根的整数部分,保存到 char [] ch 中
// 然后赋值到 bi [1]
int r = isqrt (high) + 1;
int zeros = (len - 1) >> 1;
str = int2str (r);
r = str.length ();
char ch [] = new char [r + zeros];
for (int i = 0; i < r; i ++)
{
ch [i] = str.charAt (i);
}
for (int i = r; i < ch.length; i ++)
{
ch [i] = '0';
}
bi [1] = new BigInteger (new String (ch));
// 牛顿迭代过程: X_k+1 = (X_k ^ 2 + X) / (X_k * 2)
// 通过 i = 3 - i ,可使 bi [1] 和 bi [2] 轮流保存 X_k, X_k+1
// 当 X_k+1 >= X_k 时, X_k 即为 X 的平方根的整数部分
int i = 1;
do
{
bi [3 - i] = bi [i].pow(2).add (bi [0]).divide (bi [i].shiftLeft (1));
i = 3 - i;
} while (bi [i].compareTo (bi [3 - i]) == -1);
System.out.println (bi [3 - i]);
}
}
import java.io. * ;
public class Solution {
// 将字符串转为正整数
static int str2int (String str) // 0 <= the integer <= 2 ^ 31 -1
{
int ret = 0;
for (int i = 0, j = str.length (); i < j; i ++)
{
ret = ret * 10 + str.charAt(i) - '0';
}
return ret;
}
// 将正整数转为字符串
static String int2str (int i) // 0 <= i <= 2 ^ 31 -1
{
StringBuffer sb = new StringBuffer ("0000000000");
int digit = 0;
if (i == 0)
{
return "0";
}
while (i > 0)
{
digit ++;
int low = i % 10;
i /= 10;
sb.setCharAt (10 - digit, (char)(sb.charAt(10 - digit) + low));
}
return sb.substring(10 - digit);
}
// 求正整数的平方根的整数部分 (这个是抄自 Hacker's Delight 一书的)
static int isqrt (int x) // 0 <= x <= 2 ^ 31 -1
{
int b, m = 0x40000000, y = 0;
while (m != 0)
{
b = y | m;
y >>= 1;
if (x >=b)
{
x -= b;
y |= m;
}
m >>= 2;
}
return y;
}
public static void main (String[] args) throws IOException
{
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
String str = br.readLine ();
BigInteger bi [] = new BigInteger [3];
bi [0] = new BigInteger (str); // bi [0] 保存需要求平方根的数 X
int len = str.length ();
// 如果 X 小于 1000000000,那么直接求平方根的整数部分
if (len < 10)
{
System.out.println (isqrt (str2int (str)));
return;
}
// 如果 X 的位数是奇数,high 等于 X 的最高位,否则等于最高两位
int high = str.charAt(0) - '0';
if (len % 2 == 0)
{
high = high * 10 + str.charAt(1) - '0';
}
// 将 high 的平方根的整数部分加上 1 之后乘以 10^((len - 1) / 2)
// 乘积不小于 X 的平方根的整数部分,保存到 char [] ch 中
// 然后赋值到 bi [1]
int r = isqrt (high) + 1;
int zeros = (len - 1) >> 1;
str = int2str (r);
r = str.length ();
char ch [] = new char [r + zeros];
for (int i = 0; i < r; i ++)
{
ch [i] = str.charAt (i);
}
for (int i = r; i < ch.length; i ++)
{
ch [i] = '0';
}
bi [1] = new BigInteger (new String (ch));
// 牛顿迭代过程: X_k+1 = (X_k ^ 2 + X) / (X_k * 2)
// 通过 i = 3 - i ,可使 bi [1] 和 bi [2] 轮流保存 X_k, X_k+1
// 当 X_k+1 >= X_k 时, X_k 即为 X 的平方根的整数部分
int i = 1;
do
{
bi [3 - i] = bi [i].pow(2).add (bi [0]).divide (bi [i].shiftLeft (1));
i = 3 - i;
} while (bi [i].compareTo (bi [3 - i]) == -1);
System.out.println (bi [3 - i]);
}
}
在 SGU 提交的结果:
ID: Date'n'Time: Name: Task: .Ext: Status: Time: Memory:
652002 28.10.07 02:20 rappizit 111 .JAVA Accepted 126 ms 0 kb