求和
题目描述
求 1b+2b+⋯+ab1^b+2^b+\cdots + a^b1b+2b+⋯+ab 的和除以 10410^4104 的余数。
输入格式
本题有多组数据。
第一行一个整数 NNN,表示共有 NNN 组测试数据。
对于每组数据,一行两个整数 a,ba,ba,b。
输出格式
对于每组数据,一行一个整数,表示答案。
样例 #1
样例输入 #1
1
2 3
样例输出 #1
9
提示
对于 30%30\%30% 的数据,N≤10N \le 10N≤10,a,b≤103a,b \le 10^3a,b≤103。
对于 100%100\%100% 的数据,1≤N≤1001 \le N \le 1001≤N≤100,1≤a,b≤1091 \le a,b \le 10^91≤a,b≤109。
这道题想AC比较困难,原因有以下几点:
1:数据规模庞大,无符号长整数都存不下。
2:复杂度高,易超时。
接下来给大家看一份0分代码:
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e4;
int main() {
long long n;
cin >> n;
while(n--){
long long a,b;
cin >> a >> b;
long long ans=0;
for(int i=1;i<=a;i++){
long long sum=(int)(pow(i,b))%MOD;
ans=(ans+sum)%MOD;
}
cout << ans << endl;
}
return 0;
}
以上这份代码朴实无华,用的函数是pow,开的也是long long,可结果就有点不尽人意了。3WA,7TLE。为什么呢,因为数据过于庞大,long long存不下,返回的一个负数,结果肯定不对。
其次,复杂度是n*a是肯定要超时的。
那么就用到快速幂了。
接下来给大家看一份30分代码:
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e4;
long long power(int a,int n){
int ans=1;
while(n){
if(n%2){
ans=(ans%MOD)*(a%MOD)%MOD;
}
a=(a%MOD)*(a%MOD)%MOD;
n/=2;
}
return ans;
}
int main() {
long long n;
cin >> n;
while(n--){
long long a,b;
cin >> a >> b;
long long ans=0;
for(int i=1;i<=a;i++){
long long sum=(int)(power(i,b))%MOD;
ans=(ans+sum)%MOD;
}
cout << ans << endl;
}
return 0;
}
这份代码虽然经过快速幂优化但超时任是不可免的。那还能怎么优化呢?点开标签看到数学,好开始打表,怎么打表,我们可已将它每一次sum进行输出,如下图。
打表代码:
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e4;
long long power(int a,int n){
int ans=1;
while(n){
if(n%2){
ans=(ans%MOD)*(a%MOD)%MOD;
}
a=(a%MOD)*(a%MOD)%MOD;
n/=2;
}
return ans;
}
int main() {
long long n;
cin >> n;
while(n--){
long long a,b;
cin >> a >> b;
long long ans=0;
int cnt=0;
for(int i=1;i<=a;i++){
long long sum=(int)(power(i,b))%MOD;
cout << sum << " ";
cnt++;
if(cnt%5==0){
cout << endl;
cnt=0;
}
ans=(ans+sum)%MOD;
}
cout << ans << endl;
}
return 0;
}

现在开始寻找重复部分,发现为5000个一循环,但是这个数只针对于b=2所以我们还得继续打表,经过漫长的打表过程,可以发现无论b是几,每个循环个数都是1e4的因数(不会因数的请回小学重造!)就意味每个1e4它都会循环。1e4一个循环,这正好是题目的模数,相当与我表白打了 我们可以先算出每个循环的和,再计算没有到达一个循环的部分 ,这样复杂度将大大减少,因为我们只需一个循环进行求和 ,再来一个循环求不到1e4的。具体如下。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e4;
long long power(int a,int n){
int ans=1;
while(n){
if(n%2){
ans=(ans%MOD)*(a%MOD)%MOD;
}
a=(a%MOD)*(a%MOD)%MOD;
n/=2;
}
return ans;
}
int main(){
long long n;
cin >> n;
while(n--){
long long a,b;
cin >> a >> b;
long long ans=0;
for(int i=1;i<=10000;i++){
long long sum=(int)(power(i,b))%MOD;
ans=(ans+sum)%MOD;
}
ans=a/10000*ans;
for(int i=1;i<=a%MOD;i++){
long long sum=(int)(power(i,b))%MOD;
ans=(ans+sum)%MOD;
}
cout << ans << endl;
}
return 0;
}
160

被折叠的 条评论
为什么被折叠?



