UVa 10494 If We Were a Child Again (高精度)

本文介绍了一个涉及大数除法和取模操作的问题,并提供了一种使用自定义大数类实现解决方案的方法。通过这个实例,展示了如何处理超出标准整型变量范围的大数运算。

10494 - If We Were a Child Again

Time limit: 3.000 seconds

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=97&page=show_problem&problem=1435

“Oooooooooooooooh!

If I could do the easy mathematics like my school days!!

I can guarantee, that I’d not make any mistake this time!!”

Says a smart university student!!

But his teacher even smarter – “Ok! I’d assign you such projects in your software lab. Don’t be so sad.”

“Really!!” - the students feels happy. And he feels so happy that he cannot see the smile in his teacher’s face.

 

 

The Problem

 

The first project for the poor student was to make a calculator that can just perform the basic arithmetic operations.

 

But like many other university students he doesn’t like to do any project by himself. He just wants to collect programs from here and there. As you are a friend of him, he asks you to write the program. But, you are also intelligent enough to tackle this kind of people. You agreed to write only the (integer) division and mod (% in C/C++) operations for him.

 

Input

Input is a sequence of lines. Each line will contain an input number. One or more spaces. A sign (division or mod). Again spaces. And another input number. Both the input numbers are non-negative integer. The first one may be arbitrarily long. The second number n will be in the range (0 < n < 231).

 

 
Output

A line for each input, each containing an integer. See the sample input and output. Output should not contain any extra space.

 

 
 
Sample Input

110 / 100

99 % 10

2147483647 / 2147483647

2147483646 % 2147483647

 

 

 

 

 
 
Sample Output

1

9

1

2147483646


完整代码:

/*0.019s*/

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1000;///不要开太小了!

char numstr[maxn], numstr2[maxn];

struct bign
{
	int len, s[maxn];

	bign()
	{
		memset(s, 0, sizeof(s));
		len = 1;
	}

	bign(int num)
	{
		*this = num;
	}

	bign(const char* num)
	{
		*this = num;
	}

	bign operator = (const int num)
	{
		char s[maxn];
		sprintf(s, "%d", num);
		*this = s;
		return *this;
	}

	bign operator = (const char* num)
	{
		len = strlen(num);
		for (int i = 0; i < len; i++) s[i] = num[len - i - 1] & 15;
		return *this;
	}

	///输出
	const char* str() const
	{
		if (len)
		{
			for (int i = 0; i < len; i++)
				numstr[i] = '0' + s[len - i - 1];
			numstr[len] = '\0';
		}
		else strcpy(numstr, "0");
		return numstr;
	}

	///去前导零
	void clean()
	{
		while (len > 1 && !s[len - 1]) len--;
	}

	///加
	bign operator + (const bign& b) const
	{
		bign c;
		c.len = 0;
		for (int i = 0, g = 0; g || i < max(len, b.len); i++)
		{
			int x = g;
			if (i < len) x += s[i];
			if (i < b.len) x += b.s[i];
			c.s[c.len++] = x % 10;
			g = x / 10;
		}
		return c;
	}

	///减
	bign operator - (const bign& b) const
	{
		bign c;
		c.len = 0;
		for (int i = 0, g = 0; i < len; i++)
		{
			int x = s[i] - g;
			if (i < b.len) x -= b.s[i];
			if (x >= 0) g = 0;
			else
			{
				g = 1;
				x += 10;
			}
			c.s[c.len++] = x;
		}
		c.clean();
		return c;
	}

	///乘
	bign operator * (const bign& b) const
	{
		bign c;
		c.len = len + b.len;
		for (int i = 0; i < len; i++)
			for (int j = 0; j < b.len; j++)
				c.s[i + j] += s[i] * b.s[j];
		for (int i = 0; i < c.len - 1; i++)
		{
			c.s[i + 1] += c.s[i] / 10;
			c.s[i] %= 10;
		}
		c.clean();
		return c;
	}

	///除
	bign operator / (const bign &b) const
	{
		bign ret, cur = 0;
		ret.len = len;
		for (int i = len - 1; i >= 0; i--)
		{
			cur = cur * 10;
			cur.s[0] = s[i];
			while (cur >= b)
			{
				cur -= b;
				ret.s[i]++;
			}
		}
		ret.clean();
		return ret;
	}

	///模、余
	bign operator % (const bign &b) const
	{
		bign c = *this / b;
		return *this - c * b;
	}

	bool operator < (const bign& b) const
	{
		if (len != b.len) return len < b.len;
		for (int i = len - 1; i >= 0; i--)
			if (s[i] != b.s[i]) return s[i] < b.s[i];
		return false;
	}

	bool operator > (const bign& b) const
	{
		return b < *this;
	}

	bool operator <= (const bign& b) const
	{
		return !(b < *this);
	}

	bool operator >= (const bign &b) const
	{
		return !(*this < b);
	}

	bool operator == (const bign& b) const
	{
		return !(b < *this) && !(*this < b);
	}

	bool operator != (const bign &a) const
	{
		return *this > a || *this < a;
	}

	bign operator += (const bign &a)
	{
		*this = *this + a;
		return *this;
	}

	bign operator -= (const bign &a)
	{
		*this = *this - a;
		return *this;
	}

	bign operator *= (const bign &a)
	{
		*this = *this * a;
		return *this;
	}

	bign operator /= (const bign &a)
	{
		*this = *this / a;
		return *this;
	}

	bign operator %= (const bign &a)
	{
		*this = *this % a;
		return *this;
	}
} a, b;

int main(void)
{
	char op;
	while (~scanf("%s %c %s", numstr, &op, numstr2))
	{
		a = numstr, b = numstr2;
		puts(op == '/' ? (a / b).str() : (a % b).str());
	}
	return 0;
}

### 问题分析 UVA11076 - **Add Again** 是一道关于排列组合与数学期望的题目。其核心任务是,给定一组整数(可能包含重复元素),计算出所有不同排列所组成的数字的总和。由于直接枚举所有排列的方式在大规模输入时效率极低,因此需要采用数学方法优化。 关键点包括: - 每个数字在每一位上出现的次数是相同的。 - 需要考虑重复元素的影响,使用多重集合的排列公式。 - 每一位的权重为 $10^i$,其中 $i$ 从右往左递增(即个位为 $10^0$,十位为 $10^1$ 等)。 ### 解题思路 1. **统计频率**:首先对输入数组中的每个数字进行计数。 2. **计算全排列数量**:利用阶乘和重复元素的除法公式: $$ \text{total\_permutations} = \frac{n!}{c_1! \cdot c_2! \cdot \cdots \cdot c_k!} $$ 其中 $n$ 是数组长度,$c_i$ 是第 $i$ 个数字的出现次数。 3. **计算每位贡献**:对于每个数字,它在整个排列中会在每一位上平均分布。因此,可以计算该数字在每一位上的总贡献,并乘以对应的 $10^i$ 权重。 4. **累加结果**:将每一位的总贡献相加,得到最终结果。 ### 示例代码实现 以下是一个 Python 实现示例,用于解决 UVA11076 问题: ```python import sys import math from collections import Counter def solve(): input = sys.stdin.read data = input().split() n = int(data[0]) arr = list(map(int, data[1:n+1])) freq = Counter(arr) # 计算全排列数量 (考虑重复元素) total_perms = math.factorial(n) for count in freq.values(): total_perms //= math.factorial(count) # 计算每一位的权重 power_of_ten = [10**i for i in range(n)] # 计算每个数字在每一位上的总贡献 result = 0 for digit, count in freq.items(): contribution_per_digit = (count * total_perms) // n # 每个数字在每一位上出现的次数 sum_of_positions = sum(power_of_ten) # 所有位置的权重之和 result += digit * contribution_per_digit * sum_of_positions print(result) if __name__ == "__main__": solve() ``` ### 复杂度分析 - 时间复杂度:主要操作为阶乘计算和遍历数字贡献,整体复杂度为 $O(n)$。 - 空间复杂度:使用额外空间存储频率和权重,整体为 $O(n)$。 ### 注意事项 - 阶乘计算可能会导致大数溢出,在实际比赛中建议使用高精度库或取模处理。 - 对于重复元素的处理,必须确保分母正确计算,否则会导致错误。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值