11.6 T1 謎團 (mituan)

*PS: 沒開long long被卡掉45分,果然出題人的話都不可信QAQ。。(學傻了)


與zqsz的互測題 T1 原題 POJ 1845


【題目描述】

謎團,是夜魘軍團一名強大的戰士。他來自遠古,是一種不可思議的重力生命體,是來自原始黑暗的扭曲聲音,在宇宙中的第一絲光線誕生前就存在的深淵化身。他能動用深淵之力將生物的身體污染,使之轉化爲自身的碎片“虛靈”。
“虛靈”爲謎團所控,擁有一定的戰鬥力。更爲恐怖的是,新產生的“虛靈”的 第一次攻擊將吸收被攻擊者內心的黑暗,從而分裂成若干個“虛靈”,之後的攻擊將無法產生“虛靈”,新產生的“虛靈”第一次攻擊仍可產生“虛靈”。 作爲天輝軍團智囊的你,需要知道某一時刻謎團最多可以產生多少“虛靈”,從而據
此來進行決策。具體的,謎團在 第一秒會轉化一個單位,使之變成一個“虛靈”,由於能量消耗過大,謎團在之後的時間內將不再轉化單位,使之變成“虛靈”。新產生的“虛靈”會在下一秒攻擊一次,從而分裂出 m 個“虛靈”,原有的“虛靈”仍然存在,並且將不再產生虛靈。但新產生的“虛靈”可在下一秒攻擊一次並分裂,之後也將不再產生“虛靈”(具體見樣例解釋)。給定時間 t 和分裂數 m,請你告訴天輝軍團的戰士們,在 t 秒後,謎團擁有多少個“虛靈”。
答案可能很大,要求你模一個數 k(不保證 k 是質數)。

【輸入格式】

第一行:三個整數 m,t,k,意義見題目描述

【輸出格式】

第一行:t 秒後謎團擁有的能量體個數

【樣例輸入 1】

3 3 1000

【樣例輸出 1】

13

【樣例輸入 2】

3 5 1000

【樣例輸出 2】

121

【樣例 1 解釋】

m = 3, t = 5 時:
第一秒:謎團製造 1 個“虛靈”
第二秒:1 個“虛靈”分裂出 3 個“虛靈”,此時共有 4 個“虛靈”
第三秒:第 1 秒製造的 1 個“虛靈”將不能分裂,第 2 秒製造的 3 個“虛靈”,
每個“虛靈”分裂成 3 個“虛靈”,新分裂出的“虛靈”有 9 個,此時共有 13
個“虛靈”。
最終,總共有 13 個“虛靈”

【數據規模與約定】

保證 k,m,t 及答案在 int 範圍內(注意只有答案!!!)

這裏寫圖片描述

原題意是求A^B的約數個數,因爲出題人很良心(原話),所以就改爲求首項爲1,公比爲m的等比數列的前n項和。

部分分


1~8 暴力枚舉


9~12 特殊性質:模數k是質數,因爲等比數列的前n項和爲 q^n-1/(q-1),除法的取模需要用到逆元,可以用費馬小定理做。
a^(p-1) ≡ 1(mod p) —> a^(p-2) ≡ 1/a (mod p)

ll ans=(multiply(T,M)-1)%K*multiply(K-2,M-1)%K%K;
printf("%lld",ans);

13~16 (原話)特殊性質 k不是質數,但k與m互質,用擴展歐幾里得求逆元。

但是,我用的擴展歐幾里得是要求m-1在%k意義下的逆元啊喂!! 沒有給部分分QAQ。

直接打exgcd可以的50分,前提是你開了long long ,但是我並沒有開qwqqqq(讓我自己一個人靜一會)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

long long M,T,K,ans;

long long multiply(long long n,long long a)
{
    long long sum=1,x=a;
    while(n)
    {
        if(n&1) sum=sum%K*x%K%K;
        x=x%K*x%K%K;
        n>>=1;
    }
    return sum%K;
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    long long d=exgcd(b,a%b,y,x);
    y=y-a/b*x;
    return d;
}
int main()
{
    freopen("mituan.in","r",stdin);
    freopen("mituan.out","w",stdout);
    scanf("%lld%lld%lld",&M,&T,&K);
    {
        long long x,y;
        long long d=exgcd(M-1,K,x,y);
        x%=K;
        while(x<0) x+=K/d;
        ans=(multiply(T,M)-1)%K*x%K%K;
        if(ans<0) ans+=K;
        printf("%lld",ans);
    }
    return 0;
}

17~20 沒有特殊性質 qwq


1~20

正解 1 公式求逆元

安利一個之前看到的博客(爲什麼我當時沒有好好看qwq)

http://blog.csdn.net/acdreamers/article/details/8220787

因爲費馬小定理和擴展歐幾里得算法求逆元是有侷限性的,它們都會要求a與m互素。

但是我們有一個公式,若 b|a , 則ans即爲(a/b)mod m 的答案:

這裏寫圖片描述

證明:

(a/b)mod m = ans ;

a/b = ans + k * m ;

a = ans * b + k * m * b ;

a mod ( bm ) = ans * b ;

a mod ( bm ) / b = ans ;

得證。

代碼

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define ull unsigned long long 

ull M,T,K;

ull multiply(ull n,ull a)
{
    ull sum=1,x=a;
    while(n)
    {
        if(n&1) sum=sum%K*x%K%K;
        x=x%K*x%K%K;
        n>>=1;
    }
    return sum%K;
}
int main()
{
    freopen("mituan.in","r",stdin);
    freopen("mituan.out","w",stdout);
    scanf("%lld%lld%lld",&M,&T,&K);
    K=K*(M-1);
    ull ans=(multiply(T,M)-1)/(M-1);
    printf("%lld",ans);
    return 0;
}

正解 2 二分+遞歸

數學課上的求等比數列的前n項和有一個公式,emmm,公式有很多的變形,其中有一個變形爲

這裏寫圖片描述

若另 n 和 m 都等於 t/2 ,可知

這裏寫圖片描述

所以我們要求St,只需要每次二分的遞歸下去,在遞歸的過程中取模就可以了。

另外注意遞歸的時候要分t爲奇數和偶數的情況,因爲計算機裏的/是會自動下取整的。

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long

ll M,T,K;

ll pow(ll a,ll n)
{
    ll sum=1,x=a;
    while(n)
    {
        if(n&1) sum=sum%K*x%K%K;
        x=x%K*x%K%K;
        n>>=1;
    }
    return sum;
}

ll sum(ll q,ll t) // q^0+q^1+q^2+...+q^t --> S(t+1)
{
    if(t==0) return 1;
    if(t%2==0) return (sum(q,t/2-1)%K*(1+pow(q,t/2))%K%K+pow(q,t)%K)%K; 
    //t 爲偶數,說明S(t+1)沒法直接通過S((t+1)/2)求得,就去求St,最後加上一個q^t次方 
    else return (sum(q,t/2)%K*(1+pow(q,t/2+1))%K)%K; 
    //t 爲奇數,說明S(t+1)可以直接用(S(t+1)/2)求得,又S((t+1)/2)即爲sum(q,t/2)(t/2下取整),可以直接求 (t/2+1即爲(t+1)/2)  
}
int main()
{
    freopen("mituan.in","r",stdin);
    freopen("mituan.out","w",stdout);
    scanf("%d%d%d",&M,&T,&K);
    printf("%lld",sum(M,T-1));
    return 0;
}

PS:剛剛把這篇博客搬到了博客園裏,果然背景什麼的都好漂亮(捂臉)。。雖然寫的時候很麻煩。。。但是好看啊!!! 鏈接:http://www.cnblogs.com/maple-kingdom/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章