“玲瓏杯”ACM比賽 Round #18 B -- 數論你還會快速冪【規律】
阿新 • • 發佈:2019-02-16
B -- 數論你還會快速冪
(1≤T≤1000)T(1≤T≤1000),表示有TT組資料對於每組資料輸入一行3個整數n,k,p(1≤n≤1018,0≤k≤1018,1≤p≤1018,0≤n−p≤100)n,k,p(1≤n≤1018,0≤k≤1018,1≤p≤1018,0≤n−p≤100)且模數
pp
是質數,
OUTPUT
對於每組資料輸出題目中的表示式的值
SAMPLE INPUT
2
5 2 3
7 2 3
SAMPLE OUTPUT
1
2
HINT
對於第一組樣例我們有 12+22+32+42+52=1(mod3)12+22+32+42+52=1(mod3)對於第二組樣例我們有
12+22+32+42+ 52+62+72=2(mod3)12+22+32+42+52+62+72=2(mod3)
Time Limit:5s Memory Limit:256MByte
Submissions:405Solved:85
DESCRIPTION今天HHHH在學數論,他看到一個很優美的式子:
∑ni=1ikmodp∑i=1nik mod p
一向熱衷於抱隊友大腿的HHHH便問隊友ZZZZ怎麼做
ZZZZ:"n,kn,k多大?"
HHHH:"105,105105,105"
ZZZZ:"快速冪嘛"
HHHH:"109,105109,105"
ZZZZ:"拉格朗日插值嘛"
HHHH:"1018,10181018,1018"
隊友:"讓我想想.."
INPUT 第一行是一個整數T通過打表能夠找到規律:
①首先我們知道,i^k%p和(i+p)^k%p的價值是一樣的。
那麼肯定以長度p為迴圈節,是有迴圈內容的。
②當k不是p-1的倍數的時候,我們發現,每一段長度為p的內容加和%p都是0.
②當k是p-1的倍數的時候,我們發現,每一段長度為p的內容加和都是p-1.
那麼按照這個規律寫一下即可。
注意k==0的時候。
Ac程式碼:
#include<stdio.h> #include<string.h> using namespace std; #define ll long long int ll n,p,k; ll kuaisucheng(ll a,ll b) { ll ans=0; while(b) { if(b&1) { ans=(ans+a); if(ans>=p)ans-=p; } a=(a+a); if(a>=p)a-=p; b/=2; } return ans; } ll kuaisumi(ll a,ll b) { a%=p; ll ans=1; while(b) { if(b&1) { ans=kuaisucheng(ans,a); } a=kuaisucheng(a,a); b/=2; } return ans; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%lld%lld%lld",&n,&k,&p); if(k==0) { printf("%lld\n",n%p); continue; } ll sum=0; if(k%(p-1)==0) { sum+=kuaisucheng((ll)n/p,p-1); sum%=p; } n%=p; for(ll i=1;i<=n;i++) { sum+=kuaisumi(i,k); sum%=p; } printf("%lld\n",sum%p); } }