calc(NOIP模擬賽Round 3)
阿新 • • 發佈:2017-05-25
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; } unsignedlong 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)