洛谷 P1630 求和 题解

题目链接

很巧妙的一个题,赛时没想出来。

读完题第一时间想到的是快速幂。但是因为 \(a\le10^9\),会 TLE。

这时时间复杂度的瓶颈卡在了 \(a\) 太大上。所以我们可以以 \(a\) 作为优化的突破口。再看模数 \(10000\) 这么小的数据范围,可以尝试使用模数来减少 \(a^b\) 的计算次数。

我们都知道多个数相乘以及多个数相加的结果取模与在相加或相乘的过程取模是一样的。又因为 \(a^b=a\times a\times\cdots\times a\),故也符合这个条件。由此可得:

\[\begin{aligned} {}a^b\%10000=&(a\times a\times\cdots\times a)\%10000\\ =&(a\%10000)\times(a\%10000)\times\cdots\times(a\%10000)&\\ =&(a\%10000)^b \end{aligned} \]

这时我们只要求在 \(10000\) 内的底数的 \(b\) 次方就可以了,时间复杂度 \(O(10000\log b)\)

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const ll MOD=1e4,N=1e4+100;
int n;
ll a,b,sum[N],ans;
ll quick_pow(ll a1,ll b1)
{
	ll sum=1;
	while(b1)
	{
		if(b1%2==1) sum=(sum*a1)%MOD,b1--;
		if(b1) a1=(a1*a1)%MOD,b1/=2;
	}
	return sum;
}
int main()
{
	scanf("%d",&n);
	while(n--)
	{
		ans=0;
		scanf("%lld%lld",&a,&b);
		for(int i=1;i<=10000;i++) sum[i]=(sum[i-1]+quick_pow(i,b))%MOD;
		ans=(((sum[10000]*(a/10000))%MOD)+sum[a%10000])%MOD;
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2024-08-12 11:14  MinimumSpanningTree  阅读(11)  评论(0)    收藏  举报