测试(快速幂+数学+前缀和)

洛谷 P1630 求和


 

第1题     测试 查看测评数据信息

给一个式子,求它的值,(1^b+2^b+...+a^b)%1e4

输入格式

 

第一行一个数t,表示有t组测试数据

对于每组测试数据,一行有两个整数a,b

部分数据:1<=t<=10, a,b<=1e3

对于100%的数据,1<=t<=100,1<=a,b<=1e9

 

输出格式

 

共t行,每行一个整数

 

输入/输出例子1

输入:

1

2 3

 

输出:

9

 

样例解释

 

解释一:取模的值通常是有规律的,模范围非常小可以通过找规律来解决

 

解释二(通用+推荐看看):

枚举范围大的时候,考虑两个思路,1分类,2规律(周期性)

求规律可以用打表或者用数学,打表的话注意题中特殊的数据范围,并且缩小范围

 

 

解释一:

指数很大我们可以用快速幂来解决,再逆天的数都可以在64次内解决(即O(1))。

所以b很大不是问题(逃),问题是a这么大如何解决,这样一个循环肯定是要爆的。

取模的值通常是有规律的,而且这道题给的模范围非常小,也就是说可以通过找规律来解决

原式:a^b % p

即:b个a相乘再模上p,下面用2个a来代替b个a

转换:

(a*a) % p 通过乘法取模分配律得到下面的式子

(a%p * a%p)%p (也就是b个a%p相乘再模p)

(a%p)^b % p

也就是a的范围被p限制住了,若p=100,那么a=101 相当于 a=1

所以这道题写一个前缀和就做出来了

 

解释二:

可以注意题中模数1e4这个,范围肯定有提示。

考虑分类,每个数分类,比如2的倍数,3的倍数,但是太麻烦了,且不好实现,先放着,暂不考虑

考虑规律,我们可以把模数的1e4缩小到3

 

引入一个知识,同余 

((a+b)^x ) %b   =   ( a^x)%b

根据二项式,((a+b))^x暂开可得,C(x,0)*a^0*b^x  +  C(x,1)*a^1*b^(x-1)  +  .....   +  C(x, x)*a^x*b^0

                 [   此段每个项都是xxx*b,那么%b一定是b的倍数            ]    [    最后这一段没有b]

所以整个式子%b= a^x

 

 然后找规律

 

1^b+2^b+3^b+.....+a^b

转换一下为

(1+3)^b+(2+3)^b+(3+3)^b+(1+3)^b+(2+3)^b+(3+3)^b+.....+a^b

再次转换为

1^b+2^b+3^b+1^b+2^b+3^b+.....+a^b

发现了规律,超过模数后,出现周期,周期次数为a/3,周期剩下的数为a%3,周期的和可以记录一下(前缀和),根据这一点推广到一般,得到此题的解

 

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e4+5, Mod=1e4;

int t, a, b, sum[N];
int Pow(int a, int b)
{
	if (b==1) return a%Mod;
	
	int t=Pow(a, b/2);
	if (b%2==0) return (t%Mod*t%Mod)%Mod;
	else return (t%Mod*t%Mod*a%Mod)%Mod;
} 
signed main()
{
	scanf("%lld", &t);
	while (t--)
	{
		scanf("%lld%lld", &a, &b);
		for (int i=1; i<=10000; i++) sum[i]=(sum[i-1]+Pow(i, b))%Mod;
		
		printf("%lld\n", (a/10000*sum[10000]%Mod+sum[a%10000]%Mod)%Mod);
	}
	return 0;
}

  

posted @ 2024-07-13 19:33  cn是大帅哥886  阅读(9)  评论(0编辑  收藏  举报