1144 - 数论你还会快速幂
Time Limit:5s Memory Limit:256MByte
Submissions:520Solved:114
DESCRIPTION
今天HHHH在学数论,他看到一个很优美的式子:
∑ni=1ik mod p∑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(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
25 2 37 2 3
SAMPLE OUTPUT
12
HINT
对于第一组样例我们有
12+22+32+42+52=1(mod3)12+22+32+42+52=1(mod3)对于第二组样例我们有
12+22+32+42+52+62+72=2(mod3)
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll n,k,p;
ll qsum(ll a,ll b) //快速乘防止爆 LL
{
ll ans=0;
while(b)
{
if(b&1) ans=(ans+a)%p;
a=(a+a)%p;
b/=2;
}
return ans;
}
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=(qsum(ans,a))%p;
b>>=1;
a=qsum(a,a)%p;
}
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=qsum(n/p,p-1)%p;
}
n%=p;
for(ll i=1;i<=n;i++)
sum=(sum+qpow(i,k))%p;
printf("%lld\n",(sum+p)%p);
}
return 0;
}