프로그래밍 알고리즘

[정올 3115] 긴 자리 나눗셈

꾸준한사람 2023. 1. 10. 00:19
반응형

http://www.jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=2397&sca=99&sfl=wr_hit&stx=3115 

 

JUNGOL

 

www.jungol.co.kr

#include <stdio.h>

char A[205], B[205], Ans[205];
char *pMax, *pMin; 
int MaxLen, MinLen, AnsLen;

void clear(int* p, int len = 205)
{
	for (int i = 0; i < len; i++) p[i] = 0;
}
int strlen(const char* s, int len = 0)
{
	while (s[len]) len++;
	return len;
}
int strcmp(const char* s, const char* t)
{
	while (*s && *s == *t) s++, t++;
	return *s - *t;
}
void strcpy(char* dest, const char* src)
{
	while ((*dest++ = *src++));
}
bool Input()
{
	for (int i = 0; i < 205; i++)
	{
		A[i] = B[i] = Ans[i] = 0;
	}
	pMax = pMin = nullptr;
	MaxLen = MinLen = AnsLen = 0;

	scanf("%s", A);
	scanf("%s", B);

	if ((A[0] == '0' && A[1] == 0) || (B[0] == '0' && B[1] == 0)) return false;
	else return true;
}
bool JudgeMinMax()
{
	int Alen = strlen(A), Blen = strlen(B);

	if (Alen == Blen)
	{
		int Cmp = strcmp(A, B);
		if (Cmp > 0)
		{
			pMax = A;
			MaxLen = Alen;
			pMin = B;
			MinLen = Blen;
		}
		else if (Cmp < 0)
		{
			pMax = B;
			MaxLen = Blen;
			pMin = A;
			MinLen = Alen;
		}
		else
		{
			return false; //A, B are same
		}
	}
	else if (Alen > Blen)
	{
		pMax = A;
		MaxLen = Alen;
		pMin = B;
		MinLen = Blen;
	}
	else
	{
		pMax = B;
		MaxLen = Blen;
		pMin = A;
		MinLen = Alen;
	}

	return true;
}

void Subt(char* pA, char* pB)
{
	while (*pB)
	{
		if (*pA < *pB)
		{
			//여기서 앞의 자리에서 빼올 때, 0이면 그 다음 자리에서 빼 와야 한다
			for (char* pTmp = pA - 1; ; pTmp--)
			{
				if (*pTmp == '0')
				{
					*pTmp = '9';
				}
				else
				{
					*pTmp -= 1;
					break;
				}
			}
			*pA = *pA + 10 - *pB + '0';
		}
		else
		{
			*pA = *pA - *pB + '0';
		}
		pA++; pB++;
	}
}

void Divide()
{
	while (*pMax) //큰 수가 남아 있고
	{
		int TmpMaxLen = strlen(pMax);
		//큰 수가 더 크거나 같을 때
		if ((TmpMaxLen > MinLen) || (TmpMaxLen == MinLen && strcmp(pMax, pMin) >= 0))
		{
			//해당 자리에서 뺄 수 있는 경우 -> 뺀다, 
			if (strcmp(pMax, pMin) >= 0)
			{
				Subt(pMax, pMin);
				//몫의 자리에 1을 더한다.
				Ans[AnsLen]++;
			}
			else //해당 자리에서 뺄 수 없는 경우 -> 자릿수(큰 수에서 빼고, 몫에서도 처음이 아니면 뺀다)를 낮추고 뺀다.
			{//근데 뺀 결과 큰 수의 자릿수가 줄어들 수도 있고 그대로일 수도 있다.
				//큰 수에서 자릿수 한 칸 내려서 뺀다. 큰 수의 원래 자리에서는 1을 뺀다
				Subt(pMax+1, pMin);
				//한 칸 내려서 몫의 자리에 1을 더한다.
				Ans[AnsLen + 1]++;
			}
			
			//큰 수의 자릿수 줄어든 경우
			//실제로 큰 수의 자릿수가 하나 줄어들 때만 몫의 자릿수도 하나 내린다.
			while (*pMax == '0')
			{
				pMax++;
				AnsLen++;
			}
		}
		else //큰 수가 작아졌을 때
		{
			break; //나눗셈을 끝낸다.
		}
	}

	//맨 마지막에 정답을 문자열로 변환한다.
	int s = (Ans[0] == 0) ? (1) : (0);
	int e = MaxLen - MinLen + 1;
	for (int i = s; i < e; i++)
	{
		Ans[i] += '0';
	}
}

int main(void)
{
	while (Input())
	{
		if (JudgeMinMax() == false) //same
		{
			printf("1\n");
		}
		else
		{
			Divide();
			int offset = (Ans[0] == 0) ? (1) : (0);
			printf("%s\n", Ans + offset);
		}
	}

	return 0;
}
반응형