簡體   English   中英

該程序的模算術步驟

[英]modulo arithmetic steps for this program

我已經用C編寫了這段代碼,其中a,b,cc,ma,mb,mcc,N,k都是int 但是根據問題的具體說明, Nk可能高達10^9 10^9可以存儲在我的機器的int變量中。 但是a,b,cc,ma,mb,mcc對於較大的Nk值, a,b,cc,ma,mb,mcc內部和最終值將大得多,即使在unsigned long long int變量中也無法存儲。

現在,我要打印代碼中mcc % 1000000007值。 我知道, for循環主體操作中的一些巧妙的模運算技巧可以創建正確的輸出而不會發生任何溢出,並且還可以使程序節省時間。 作為模數運算的新手,我無法解決這個問題。 有人可以指出這些步驟嗎?

ma=1;mb=0;mcc=0;
for(i=1; i<=N; ++i){
    a=ma;b=mb;cc=mcc;
    ma = k*a + 1;
    mb = k*b + k*(k-1)*a*a;
    mcc = k*cc + k*(k-1)*a*(3*b+(k-2)*a*a);
}
printf("%d\n",mcc%1000000007);

我的嘗試:

我使用a,b,cc,ma,mb,mcc long long並且做到了這一點。 可以進一步優化嗎?

ma=1;mb=0;cc=0;
ok = k*(k-1);
for(i=1; i<=N; ++i){
    a=ma;b=mb;
    as = (a*a)%MOD;

    ma = (k*a + 1)%MOD;

    temp1 = (k*b)%MOD;
    temp2 = (as*ok)%MOD;
    mb = (temp1+temp2)%MOD;

    temp1 = (k*cc)%MOD;
    temp2 = (as*(k-2))%MOD;
    temp3 = (3*b)%MOD;
    temp2 = (temp2+temp3)%MOD;
    temp2 = (temp2*a)%MOD;
    temp2 = (ok*temp2)%MOD;
    cc = (temp1 + temp2)%MOD;
}
printf("%lld\n",cc);

讓我們看一個小例子:

mb = (k*b + k*(k-1)*a*a)%MOD;

在此,考慮到k*bk*(k-1)*a*a可能溢出,所以總和也可能溢出

(x + y) mod m = (x mod m + y mod m) mod m

我們可以重寫它( x= k*by=k*(k-1)*a*am=MOD

mb = ((k*b) % MOD + (k*(k-1)*a*a) %MOD) % MOD

現在,我們可以再走一步。 以來

x * y mod m = (x mod m * y mod m) mod m

我們還可以將x=k*(k-1)y=a*a的乘法k*(k-1)*a*a % MOD重寫為

((k*(k-1)) %MOD) * ((a*a) %MOD)) % MOD

我確定您可以做剩下的事。 盡管您可以在所有位置灑% MOD ,但應考慮John的提示 ,仔細考慮是否需要它:

將兩個n位數字相加會產生最多n + 1位數字,將n位數字與m位數字相乘會得到最多n + m位的結果。

因此,在某些地方您將需要使用模數屬性,在某些地方您肯定不需要它,但這是您的工作;)。

按照以下步驟構建模板類是一個很好的練習:

template <int N>
class modulo_int_t
{
public:
    modulo_int_t(int value) : value_(value % N) {}
    modulo_int_t<N> operator+(const modulo_int_t<N> &rhs)
    {
        return modulo_int_t<N>(value_ + rhs.value) ;
    }
    // fill in the other operations
private:
    int value_ ;
} ;

然后使用modulo_int_t <1000000007>對象而不是int編寫操作。 免責聲明:在適當的地方使用long long並注意消除負面差異...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM