繁体   English   中英

编码竞赛:如何存储大量数字并找到其所有组合模数P

[英]Coding Competitions: How to store large numbers and find its all combination modulus P

我已经开始进行竞争性编程了,大多数时候我发现数字的输入大小就像

     1 <= n <=  10^(500). 

所以我知道那将是不能存储在简单的int内存中的500位数字。 我知道c和c ++。

我想我应该使用数组。 但是后来我对如何找到感到困惑

   if ( (nCr % P) == 0 )  //for all (0<=r<=n)//

我认为我会将其存储在数组中,然后找到nCr。 这将需要对数字进行乘法和除法编码,而模数又如何。

还有其他办法吗?

谢谢。

我想您不想自己编写乘法和除法代码,而是使用类似GNU MP Bignum库的代码http://gmplib.org/

关于大量库,我使用了ttmath ,它提供任意长度的整数,浮点数等,以及一些非常好的操作,所有操作都相对较小。

但是,如果您只是想弄清楚什么是(n ^ e)mod m,即使没有非常大的数量计算,也可以对e的很大值执行此操作。 下面是我添加到本地ttmath库中的函数,以实现此目的:

/*!
        mod power this = (this ^ pow) % m
        binary algorithm (r-to-l)

        return values:
        0 - ok
        1 - carry
        2 - incorrect argument (0^0)
    */
    uint PowMod(UInt<value_size> pow, UInt<value_size> mod)
    {
        if(pow.IsZero() && IsZero())
        // we don't define zero^zero
        return 2;

        UInt<value_size> remainder;
        UInt<value_size> x = 1;

        uint c = 0;

        while (pow != 0)
        {
            remainder = (pow & 1 == 1);
            pow /= 2;
            if (remainder != 0)
            {
                c += x.Mul(*this);
                x = x % mod;                                
            }

            c += Mul(*this);
            *this = *this % mod;        
        }

        *this = x;
        return (c==0)? 0 : 1;
    }

我不认为您需要为此算法存储大于n ^ 2的数字。 如果您不想使用这些标头,则应该易于修改,以便删除与ttmath相关的方面。

您可以通过查找模幂来在线查找数学的详细信息。

如果必须计算nCr mod p(其中p是素数),则可以计算阶乘mod p,然后使用模逆来找到nCr mod p。 如果必须找到nCr mod m(其中m不是素数),则可以将m分解为素数,然后使用中国剩余定理(CRT)来找到nCr mod m。

#include<iostream>
using namespace std;
#include<vector>

/* This function calculates (a^b)%MOD */
long long pow(int a, int b, int MOD)
{
    long long x=1,y=a; 
    while(b > 0)
    {
        if(b%2 == 1)
        {
            x=(x*y);
            if(x>MOD) x%=MOD;
        }
        y = (y*y);
        if(y>MOD) y%=MOD; 
        b /= 2;
    }
    return x;
}

/*  Modular Multiplicative Inverse
    Using Euler's Theorem
    a^(phi(m)) = 1 (mod m)
    a^(-1) = a^(m-2) (mod m) */
long long InverseEuler(int n, int MOD)
{
    return pow(n,MOD-2,MOD);
}

long long C(int n, int r, int MOD)
{
    vector<long long> f(n + 1,1);
    for (int i=2; i<=n;i++)
        f[i]= (f[i-1]*i) % MOD;
    return (f[n]*((InverseEuler(f[r], MOD) * InverseEuler(f[n-r], MOD)) % MOD)) % MOD;
}

int main()
{    
    int n,r,p;
    while (~scanf("%d%d%d",&n,&r,&p))
    {
        printf("%lld\n",C(n,r,p));
    }
}

在这里,我使用了很长的int来存储数字。

在许多。 在这些编码竞赛中,很多情况下,您的想法是您实际上并没有计算这些大数字,而是想出了如何在不计算的情况下回答问题的方法。 例如:

What are the last ten digits of 1,000,000! (factorial)? 

这个数字超过五百万个数字。 但是,即使没有计算机,我也可以不使用笔和纸来回答这个问题。 或问一个问题:什么是(2014 ^ 2014)模153? 这是用C计算这个的简单方法:

int modulo = 1;
for (int i = 0; i < 2014; ++i) modulo = (modulo * 2014) % 153;

同样,您避免使用6,000位数字进行计算。 (实际上您可以更快地完成此操作,但我不是要参加比赛)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM