== 소감 ==
|| 2006-01-08 Accepted 4.244 444 ||
Closed Form 구하는데 약 3~4시간 걸린 것 같다. 계차수열을 이용해서 다음과 같은 Closed Form을 구했다.
{{| T(n) = (n4 - 6n3 + 23n2 - 18n + 24) / 24 |}}
이론상으론 O(1) 시간만에 되겠지만 문제는 입력범위가 2 31 - 1 까지 들어올 수 있기 때문에 고정도 연산을 수행해야 한다. GNU C++ 이나 Java는 고정도 연산을 수행할 수 있는 클래스를 포함하고 있으나, 윈도우 C++에는 없다(혹, 내가 못찾는 것일수도 있다). 따라서 고정도 연산을 수행할 수 있는 클래스를 짰다. 성능이 너무 떨어진다. O(1) 을 O(n5) 정도로 바꿔 놓은 듯한 느낌이다. 이 Class를 개선한뒤 다시 테스트 해봐야 겠다.
== 코드 ==
=== BigInteger.h ===
{{{~cpp
//////////////////////////////////////////////////////////////////////////
// Big Integer Class - C++
// 만든이 : Moon, Bo-chang.
// 만든 날짜 : 2006 / 1 / 7
// 마지막으로 수정한 날짜 :
// 주의 : 오버플로우 처리 안함
// 지원하는 연산 : +(덧셈), -(뺄셈), *(곱셈), /(나눗셈) - 나눗셈 연산에서 나머지는 버린다.
// 함수 호출이 모두 복사로 이루어지므로 성능이 크게 떨어진다.
//////////////////////////////////////////////////////////////////////////
#pragma once
#include
using namespace std;
#include
#define MAXDIGITS 100
#define PLUS 1
#define MINUS -1
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
class BigInteger
{
public:
char digit[MAXDIGITS];
int signbit;
int lastdigit;
public:
BigInteger(int n)
{
int i;
lastdigit = 0;
signbit = (n < 0) ? MINUS : PLUS;
while (n / 10)
{
digit[lastdigit++] = n % 10;
n /= 10;
}
digit[lastdigit] = n % 10;
for (i = lastdigit + 1; i < MAXDIGITS; i++)
digit[i] = 0;
}
BigInteger()
{
int i;
for (i = 0; i < MAXDIGITS; i++)
digit[i] = 0;
signbit = PLUS;
lastdigit = 0;
}
void print()
{
if (signbit == MINUS) cout << "-";
for (int i = lastdigit; i >= 0; i--)
cout << (int)digit[i];
}
void input()
{
int startI = 0;
int i, j;
char temp[MAXDIGITS];
while (cin.peek() == ' ' || cin.peek() == '\n')
cin.get();
cin >> temp;
lastdigit = strlen(temp) - 1;
signbit = PLUS;
if (temp[0] == '-')
{
signbit = MINUS;
startI = 1;
lastdigit--;
}
else if (temp[0] == '+')
{
startI = 1;
lastdigit--;
}
j = 0;
for (i = lastdigit + startI; i >= startI; i--)
digit[j++] = temp[i] - '0';
}
public:
friend void elminatePreZero(BigInteger& n)
{
while (n.lastdigit > 0 && n.digit[n.lastdigit] == 0)
n.lastdigit--;
if (n.lastdigit == 0 && n.digit[0] == 0)
n.signbit = PLUS;
}
friend int compare(BigInteger& a, BigInteger& b)
{
int i;
if (a.signbit == MINUS && b.signbit == PLUS) return PLUS;
if (a.signbit == PLUS && b.signbit == MINUS) return MINUS;
if (b.lastdigit > a.lastdigit) return (PLUS * a.signbit);
if (a.lastdigit > b.lastdigit) return (MINUS * a.signbit);
for (i = a.lastdigit; i >= 0; i--)
{
if (a.digit[i] > b.digit[i])
return (MINUS * a.signbit);
if (b.digit[i] > a.digit[i])
return (PLUS * a.signbit);
}
return 0;
}
friend void shiftDigit(BigInteger& n, int d)
{
int i;
if (n.lastdigit == 0 && n.digit[0] == 0) return;
for (i = n.lastdigit; i >= 0; i--)
n.digit[i+d] = n.digit[i];
for (i = 0; i < d; i++) n.digit[i] = 0;
n.lastdigit = n.lastdigit + d;
}
friend BigInteger operator+(BigInteger a, BigInteger b)
{
int carry;
BigInteger ret;
int i;
if (a.signbit == MINUS && b.signbit == PLUS)
{
a.signbit = PLUS;
ret = b - a;
a.signbit = MINUS;
}
else if (a.signbit == PLUS && b.signbit == MINUS)
{
b.signbit = PLUS;
ret = a - b;
b.signbit = MINUS;
}
else
{
ret.signbit = a.signbit;
ret.lastdigit = MAX(a.lastdigit, b.lastdigit) + 1;
carry = 0;
for (i = 0; i <= ret.lastdigit; i++)
{
ret.digit[i] = (carry + a.digit[i] + b.digit[i]) % 10;
carry = (carry + a.digit[i] + b.digit[i]) / 10;
}
elminatePreZero(ret);
}
return ret;
}
friend BigInteger operator-(BigInteger a, BigInteger b)
{
BigInteger ret;
int borrow, v;
int i;
if (a.signbit == MINUS || b.signbit == MINUS)
{
b.signbit = -1 * b.signbit;
ret = a + b;
b.signbit = -1 * b.signbit;
return ret;
}
if (compare(a,b) == PLUS)
{
ret = b - a;
ret.signbit = MINUS;
return ret;
}
ret.lastdigit = MAX(a.lastdigit,b.lastdigit);
borrow = 0;
for (i = 0; i <= ret.lastdigit; i++)
{
v = a.digit[i] - borrow - b.digit[i];
if (a.digit[i] > 0)
borrow = 0;
if (v < 0)
{
v = v + 10;
borrow = 1;
}
ret.digit[i] = v % 10;
}
elminatePreZero(ret);
return ret;
}
friend BigInteger operator*(BigInteger a, BigInteger b)
{
BigInteger row, tmp, ret;
int i, j;
row = a;
for (i = 0; i <= b.lastdigit; i++)
{
for (j = 1; j <= b.digit[i]; j++)
{
tmp = ret + row;
ret = tmp;
}
shiftDigit(row, 1);
}
ret.signbit = a.signbit * b.signbit;
elminatePreZero(ret);
return ret;
}
friend BigInteger operator/(BigInteger a, BigInteger b)
{
BigInteger row, tmp, ret;
int asign, bsign;
int i;
ret.signbit = a.signbit * b.signbit;
asign = a.signbit;
bsign = b.signbit;
a.signbit = PLUS;
b.signbit = PLUS;
ret.lastdigit = a.lastdigit;
for (i = a.lastdigit; i >= 0; i--)
{
shiftDigit(row, 1);
row.digit[0] = a.digit[i];
ret.digit[i] = 0;
while (compare(row, b) != PLUS)
{
ret.digit[i]++;
tmp = row - b;
row = tmp;
}
}
elminatePreZero(ret);
a.signbit = asign;
b.signbit = bsign;
return ret;
}
};
}}}
=== main.cpp ===
{{{~cpp
#include "BigInteger.h"
int main()
{
int nCase;
BigInteger a(6), b(23), c(18), d(24);
BigInteger n, result;
cin >> nCase;
for (int i = 0; i < nCase; i++)
{
n.input();
result = (n * n * n * n - a * n * n * n + b * n * n - c * n + d) / d;
result.print();
cout << endl;
}
return 0;
}
}}}
----
[HowManyPiecesOfLand?]