1. 程式人生 > >calc(NOIP模擬賽Round 3)

calc(NOIP模擬賽Round 3)

sum int 快速冪 else 定義 urn open left ans

原題:

D e s c r i p t i o n

給三個正整數n,m和p,求(n^1+...n^m) mod p。 Input

一行,三個整數n,m和p。 Output

輸出答案。 S a m p l e I n p u t

2 2 5

S a m p l e O u t p u t

1

數 據 範 圍

n,p<=10^8 m<=10^17 時 限

1s

首先看到m範圍就知道是快速冪了對吧。

然後我們想想看。假如是平常的快速冪的話時間復雜度為O(M)

TLE了對吧,然後我們想想有沒有LOG級別的算法,就是加法也做到LOG。

考場上尋找DP式去了。。

a^1+a^2+a^3+a^4=(1+a^2)(a^1+a^2);

所以。。以此類推

f[n]=(1+f[n>>1])%p*f[n>>1]%p;

但是n為奇數的時候顯然無法得到這個式子

所以奇數時:

f[n]=f[n-1]+a^n(快速冪)

然後算法復雜度O(logm)

快多啦!

然後就是代碼。。

註意!在這道題中所有的數據都要定義為 long long ,否則會掛掉!

就是因為考場上太弱了,寫了個int都沒發現。我的70分/(ㄒoㄒ)/~~。

下面貼代碼

#include<iostream>
#include<cstdio>
using namespace std;
unsigned long long num[500
]; unsigned long long n,m,p; unsigned long long ans; unsigned long long work(unsigned long long x) { unsigned long long tmp=x; unsigned long long qaq=1; int tt=1; while(tmp) { if(tmp&1)qaq=(qaq*num[tt])%p; tt++; tmp>>=1; } return qaq; } unsigned
long long dfs(unsigned long long x) { if(x==1)return n%p; if(x==0)return 1; if(x%2==0)return (dfs(x/2)%p*(1+work(x/2))%p)%p; else return (dfs(x-1)%p+work(x)%p)%p; } int main(){ freopen("calc.in","r",stdin); freopen("calc.out","w",stdout); scanf("%lld%lld%lld",&n,&m,&p); unsigned long long sum=1,tot=1; num[1]=n; while(sum<m){ num[++tot]=(num[tot-1]*num[tot-1])%p; sum<<=1; } ans=dfs(m); printf("%lld\n",ans); fclose(stdin); fclose(stdout); }

calc(NOIP模擬賽Round 3)