Easy Summation
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 131072/131072K (Java/Other)
Total Submission(s) : 6 Accepted Submission(s) : 1
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Given two integers n and k. Let f(i)=ik, please evaluate the sum f(1)+f(2)+...+f(n). The problem is simple as it looks, apart from the value of n in this question is quite large.
Can you figure the answer out? Since the answer may be too large, please output the answer modulo 109+7.
Input
Each of the following T lines contains two integers n(1≤n≤10000) and k(0≤k≤5).
Output
Sample Input
3 2 5 4 2 4 1
Sample Output
33 30 10
Source
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std;
long long pow2(long long a,int b)//快速幂 位运算版
{long long r=1,base=a;while(b){if(b&1) r=(r*base)%1000000007;base=(base*base)%1000000007;b>>=1;}return r;
}
int main()
{int m;cin>>m;while(m--){int n,k;cin>>n>>k;long long sum=0;for(int i=1;i<=n;i++){sum+=pow2(i,k);sum=sum%1000000007;//1000000007}cout<<sum<<endl;}return 0;
}
快速幂的思想:
首先,快速幂的目的就是做到快速求幂,假设我们要求a^b,按照朴素算法就是把a连乘b次,这样一来时间复杂度是O(b)也即是O(n)级别,快速幂能做到O(logn),快了好多好多。它的原理如下:
假设我们要求a^b,那么其实b是可以拆成二进制的,该二进制数第i位的权为2^(i-1),例如当b==11时
1 int poww(int a,int b){ 2 int ans=1,base=a; 3 while(b!=0){ 4 if(b&1!=0) 5 ans*=base; 6 base*=base; 7 b>>=1; 8 } 9 return ans; 10 }
代码很短,死记也可行,但最好还是理解一下吧,其实也很好理解,以b==11为例,b=>1011,二进制从右向左算,但乘出来的顺序是 a^(2^0)*a^(2^1)*a^(2^3),是从左向右的。我们不断的让base*=base目的即是累乘,以便随时对ans做出贡献。
其中要理解base*=base这一步,看:::base*base==base^2,下一步再乘,就是base^2*base^2==base^4,然后同理 base^4*base4=base^8,,,,,see?是不是做到了base-->base^2-->base^4-->base^8-->base^16-->base^32.......指数正是 2^i 啊,再看上 面的例子,a??= a^(2^0)*a^(2^1)*a^(2^3),这三项是不是完美解决了,,嗯,快速幂就是这样。
顺便啰嗦一句,由于指数函数是爆炸增长的函数,所以很有可能会爆掉int的范围,根据题意决定是用 long long啊还是unsigned int啊还是mod某个数啊自己看着办。