浙江工业大学校赛 竹之书(大数,同余定理)

本文介绍了一个名为“竹之书”的编程问题,该问题要求计算一个由正整数组成的密文序列的key值。提供了完整的Java代码实现,包括如何读取输入数据、计算序列的总和与乘积,并利用BigInteger类解决大数运算问题。

竹之书

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 548    Accepted Submission(s): 86


Problem Description
由于某些原因菲莉丝拿到了贤者之石,所以好像变得很厉害了
好像变得很厉害的菲莉丝想要炼成幻想乡,其中有一个原料是稗田一族对幻想乡历史的记录。现在菲莉丝拿到了一个被某只魔粘性精神体加密过的的卷轴。
密文通过原文和一个正整数key加密形成,而key和密文又有一定关联。
现给出密文,求key值

已知密文s和key值关系如下
已知密文s是一串正整数s1,s2,s3……sn,A为s中所有元素的和,B为s中所有元素的积,key为B mod A

数据范围
si,A在(0,1e17]范围内
0<n<=100000
 

Input
第一行T表示数据组数
接下来每组第一行一个n,代表s的长度
接下来n行,每行一个正整数si
 

Output
每组一行,key值
 

Sample Input
2 4 1 2 3 4 6 5 6 7 8 9 9
 

Sample Output
4 32
import java.util.*;
import java.*;
import java.io.*;
import java.math.BigInteger;
public class Main {
    
    
    
    public static void main(String args[]) throws IOException
    {
        int t;
        int n;
        Scanner input=new Scanner(System.in);
        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        
        t=input.nextInt();
        long a[]=new long[100005];
        BigInteger num;
        for(int i=1;i<=t;i++)
        {

            num=BigInteger.valueOf(1);
            long sum=0;
            n=input.nextInt();
            
        
            for(int j=1;j<=n;j++)
            {
                a[j]=input.nextLong();
                sum+=a[j];
            }
            for(int j=1;j<=n;j++)
            {
                num=num.multiply(BigInteger.valueOf(a[j]));
                num=num.mod(BigInteger.valueOf(sum));
            
            }
        
    
            System.out.println(num);
        }
        
        
    }

}


转载于:https://www.cnblogs.com/dacc123/p/8228535.html

### 中国剩余定理的大数实现 #### 定义与背景 中国剩余定理是一种用于解决模线性方程组的经典方法,特别适用于模数互素的情况[^1]。该定理的核心在于通过分解问题并逐步求解的方式找到满足条件的唯一解。 对于大数运算场景下的中国剩余定理实现,通常会借助专门设计的大数处理库来完成复杂的数值计算。例如,在实际应用中可以采用 MIRACL (Multiprecision Integer and Rational Arithmetic C/C++ Library) 或其他类似的工具支持高效的大数操作[^3]。 --- #### 数学基础 假设给定一组两两互质的正整数 \( m_1, m_2, \dots, m_k \),以及对应的余数序列 \( a_1, a_2, \dots, a_k \),则存在唯一的最小非负整数 \( x \) 满足以下同余方程组: \[ \begin{aligned} &x \equiv a_1 \pmod {m_1}, \\ &x \equiv a_2 \pmod {m_2}, \\ &\vdots \\ &x \equiv a_k \pmod {m_k}. \end{aligned} \] 其中,\( M = m_1 \cdot m_2 \cdots m_k \) 是所有模数的乘积,而每个子项定义为 \( M_i = M / m_i \)[^4]。进一步地,可以通过扩展欧几里得算法求出逆元 \( y_i \),使得 \( M_i \cdot y_i \equiv 1 \pmod {m_i} \) 成立。最终通解形式可表示为: \[ x = \sum_{i=1}^{k}{(a_i \cdot M_i \cdot y_i)} \pmod M. \] --- #### 算法伪代码描述 以下是基于上述理论构建的一个通用算法框架,适合应用于大数环境: ```python def chinese_remainder_theorem(moduli, remainders): """ 使用中国剩余定理求解模线性方程组。 参数: moduli -- 列表,存储各模数 mi remainders -- 列表,存储对应余数 ai 返回值: 整数型变量,代表所求数字 x 的最小非负解。 """ from math import gcd total_modulus = 1 result = 0 # 验证输入数据合法性 assert len(moduli) == len(remainders), "Moduli 和 Remainders 应具有相同长度" for i in range(len(moduli)): for j in range(i + 1, len(moduli)): if gcd(moduli[i], moduli[j]) != 1: raise ValueError(f"模数 {moduli[i]} 和 {moduli[j]} 不互素") # 计算总模数 M 及其分量 Mi for modulus in moduli: total_modulus *= modulus # 构造特解部分 for modulus, remainder in zip(moduli, remainders): partial = total_modulus // modulus # Mi = M / mi inverse = pow(partial, -1, modulus) # yi ≡ inv(Mi, mi) result += remainder * partial * inverse # 更新结果 return result % total_modulus # 返回最小非负解 ``` 此函数实现了标准版本的 CRT 方法,并且兼容 Python 中内置的支持整数幂次取模运算的功能 `pow(base, exp, mod)` 来替代传统方式寻找乘法逆元的过程。 --- #### 示例程序运行说明 考虑题目提到的例子:“一个整数除以三余二,除以五余三,除以七余二”,即已知参数列表分别为 `[3, 5, 7]` 和 `[2, 3, 2]` 。调用上面定义好的功能模块即可得到解答过程如下所示: ```python if __name__ == "__main__": mods = [3, 5, 7] rems = [2, 3, 2] solution = chinese_remainder_theorem(mods, rems) print(solution) # 输出应为 23 ``` 执行完毕之后将会打印出正确答案——数字 **23** ,验证无误! --- #### 注意事项 当面对超规模的数据集或者更高精度需求时,则可能需要引入外部依赖包比如 GMPY2 提供更高效的底层优化机制;另外还需注意边界情况处理如空集合传入等问题以免引发异常中断行为发生。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值