SGU 111 Very simple problem 翻译 题解
111. Very simple problem 每个测试点时间限制: 0.50 sec.
给你一个自然数X,输出平方小于或等于X的最大整数。
输入 输入包含一个自然数 X (1≤X≤101000).
输出 输出答案
样例输入 16
样例输出 4 |
================================华丽的分割线 ================================
第一眼,觉得是个水题,看了数据范围发现暴难!
我的第一个做法是,网上看到的一个:用X减1,再-3,再-5,再-7,再-2k-1,到小于0,输出K-1。
最开始觉得不行,后来试了一下,发现:1=1=1^2
1+3=4=2^2
1+3+5=9=3^2
...
1+...+2*k-1=k^2
感觉比下面要介绍的方法简单得多,尝试了一下,TLE了。。。。
然后就是笔算开根,看了半天才看懂,推荐个地方吧:
http://www.gaokw.com/gwy/xingce/4183.html,有图有解释,觉得不错。
再一个,我的代码应该好懂,因为函数都单独抽取出来了,没堆在一起,有面向对象的感觉,呵呵。
#include <math.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #define USE 4 #define INF 10000 #define MAX 500 typedef struct { int num[MAX], len; }bignum; char str[1000]; bignum a, b, c; void add(bignum *a, int k) { int i; for(i = 1; i <= a->len; i++){ if(!k){ break; } a->num[MAX - i] += k; k = a->num[MAX - i] / INF; a->num[MAX - i] %= INF; } if(k){ a->num[MAX - i] = k; a->len++; } } void dec(bignum *a, bignum *b) { int i, j = 0; int len = b->len; for(i = 1; i <= len; i++){ a->num[MAX - i] = a->num[MAX - i] - b->num[MAX - i] - j; j = 0; while(a->num[MAX - i] < 0){ a->num[MAX - i] += INF; j++; } } if(j){ a->num[MAX - i] -= j; } for(i = a->len; i >= 1; i--){ if(a->num[MAX - i]){ break; } } a->len = i; } void mul(bignum *a, int k) { int i, j = 0; //考虑一个特殊情况, k=0时 if(k == 0){ memset(a, 0, sizeof(bignum)); return; } for(i = 1; i <= a->len; i++){ a->num[MAX - i] = a->num[MAX - i] * k + j; j = a->num[MAX - i] / INF; a->num[MAX - i] %= INF; } if(j){ a->num[MAX - i] = j; a->len++; } } void output(bignum *a) { int i; printf("%d", a->num[MAX - a->len]); for(i = a->len - 1; i >= 1; i--){ printf("%.*d", USE, a->num[MAX - i]); } printf("\n"); } int com(bignum *a, bignum *b) { int i; if(a->len != b->len){ return a->len - b->len; } for(i = a->len; i >= 1; i--){ if(a->num[MAX - i] != b->num[MAX - i]){ return a->num[MAX - i] - b->num[MAX - i]; } } return 0; } int getnum(int len) { static int start = 0; int i, n = 0; for(i = 0; i < len; i++){ n *= 10; n += str[start + i] - '0'; } start += len; return n; } int check(int k) { memcpy(&c, &b, sizeof(b)); //c = (20 * b + k) * k; mul(&c, k * 20); add(&c, k * k); if(com(&a, &c) >= 0){ return 1; } return 0; } int main(int argc, char **argv) { int i, j, t, n; scanf("%s", str); n = strlen(str); if(n & 1){ j = getnum(1); }else{ j = getnum(2); } n = (n + 1) / 2; t = sqrt(j); add(&a, j - t * t); add(&b, t); for(i = 2; i <= n; i++){ mul(&a, 100); add(&a, getnum(2)); for(j = 9; j >= 0; j--){ if(check(j)){ break; } } dec(&a, &c); mul(&b, 10); add(&b, j); } output(&b); return 0; }