病毒分裂(分治+快速冪)

【問題描述】

  A學校的實驗室新研製出了一種十分厲害的病毒。由於這種病毒太難以人工製造了,所以專家們在一開始只做出了一個這樣的病毒。

  這個病毒被植入了特殊的微型芯片,使其可以具有一些可編程的特殊性能。最重要的一個性能就是,專家們可以自行設定病毒的分裂能力 K,假如現在有x 個病毒,下一個分裂週期將會有 Kx個一模一樣的病毒。你作爲該實驗室的數據分析員,需要統計出在分裂到第N個週期前,一共有多少個病毒單體進行了分裂。一開始時總是隻有一個病毒,這個局面算作第一個週期。由於答案可能很大,專家們只需要你告訴他們對給定的P取模後的答案。

【輸入格式】

  一行三個整數,依次是K, N, P。

【輸出格式】

  一行一個整數,你的答案(對P取模) 。

【輸入樣例】

【樣例1】
 5 3 7

【樣例2】
 2 6 23

【輸出樣例】

【樣例1】
 6

【樣例2】
 8

【樣例解釋】

  樣例一解釋:第一個週期有 1 個病毒,產生了一次分裂。第二個週期有 1*5=5 個病毒, 這五個病毒都會分裂。 所以第三個週期前一共進行了1+5等於 6 次分裂。 答案即爲6 mod 7 = 6。

【數據範圍】

1 < N < 10^18
1 < K , P < 2^31

這道題求的是K^0+K^1+…+K^n-2取餘,就是求冪的和,又因爲N的值很大,如果暴力求解肯定會超時。所以要用快速冪優化,但是用快速冪也會超時,這裏就用分治二分+快速冪,數據全過沒問題。最好數據類型全部用long long,省心。

#include<stdio.h>
#include<math.h>
using namespace std;
long long k,n,p;
//二分+快速冪求和 

long long qkpow(long long k,long long n) 
{
    long long ans=1,t=k;
    while(n>0)
    {
        if(n&1) ans=(ans*t)%p;
        n>>=1;
        t=(t*t)%p;
    } 
    return ans;
}

long long solve(long long k,long long n) //二分求和
{
    if(n==1) return k;
    long long t1=solve(k,n>>1);
    long long t2=qkpow(k,n>>1);

    if(n&1) return (t1+(t1*t2)%p+qkpow(k,n))%p; //奇
    else return (t1+(t1*t2)%p)%p; //偶
}

int main()
{
    freopen("virus.in","r",stdin);
    freopen("virus.out","w",stdout);
    scanf("%I64d %I64d %I64d",&k,&n,&p);

    long long ans=(solve(k,n-2)+1)%p;
    printf("%I64d",ans);
    return 0;
}
發佈了48 篇原創文章 · 獲贊 6 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章