题解 P1630 【求和】
- 前置知识:
(a+y)^x=a^x(mod y)
快速幂:比较简单的数论基础,如果没有学过,快速幂传送门
- 当我看到这一题时,我脑子里冒出了两个想法:
-
这题的快速幂是妥妥的(√)
-
在吗?模数是不是质数?可不可以套逆元?(×)然而沙雕的我却忽略了模数那小到可怜的大小,显然这一题必须针对模数进行操作,且时间复杂度与x,y无关,所以:a^x 可化为 (a%10000)^x所以我们只要用一个sum前缀和数组存储前i个数的次方和:
sum[i]=(sum[i-1]+qpow(i,b))%mod;
然后O(1)求答案:
ans=n/10000*sum[10000]+sum[n%10000]
详见代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;//同#define LL long long
const LL mod=10000;
LL a,b,ans,sum[10010];
inline LL qpow(LL a,LL p,LL mod){//快速幂模板,求a^p
LL sum=1;
while(p){
if(p&1){
sum=sum*a%mod;
}
a=a*a%mod;
p>>=1;//通过倍增的方法求幂;
}
return sum%mod;
}
int main(){
LL Time;
scanf("%lld",&Time);
while(Time--){
scanf("%lld%lld",&a,&b);
for(register LL i=1;i<=10000;++i){
sum[i]=(sum[i-1]+qpow(i,b,mod))%mod;//针对模数下手,用数组求出(i<=10000)的前缀和
}
ans=(a/10000*sum[10000]+sum[a%10000])%mod;//通过上文所将的前缀和以O(1)求出答案;
printf("%lld\n",ans);
}
}
综上所述,预处理O(mod),求值O(1),所以时间复杂度为O(T*mod),空间复杂度为O(10000),能够通过评测