Description
定义F(n,k) = 1^k +2^k +3^k …… +n^k。
(1<=n<=10 ^17 , 1<=k<=15)
Input
第一行输入一个整数T(1<=T<=5),共T组测试数据
每组数据一行,包含两个整数 n k
Output
对应每组输入,输出F(n,k) mod 10007,占单独的一行(10007是一个质数)
Sample Input
2 100 1 2 10
Sample Output
5050 1025
题目刚看完以为是要求通项,感觉很像高中数竞讲的用组合数表示的方法。。不过完全没有思路。不过突然发现答案只需要模10007输出。于是题目就很简单了。
因为对于大于10007的i,被10007同余后i^k都是和前面的重复的。
所以对于一个n = 10007*p + t;
F(n, k) = p*F(10007, k) + F(t, k) (mod 10007)
于是实现就很简单了。由于不想分开写p为0和不为0的情况,所以统一写成了一种,可能效率不怎么高。
此处求指数采用了快速幂,起始k不是很大不用也是OK的。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <set> #include <map> #include <queue> #include <string> #define N 10007 #define LL long long using namespace std; LL s[10008]; LL quickPow(int x, int n) { int p = 1; while (n) { p *= n&1 ? x : 1; p %= N; n >>= 1; x *= x; x %= N; } return p; } void Work() { LL n; int k; LL ans; scanf("%lld%d", &n, &k); s[0] = 0; for (int i = 1; i <= N; ++i) { s[i] = (s[i-1] + quickPow(i, k))%N; } int v, t; v = n/N; t = n%N; ans = (v*s[N] + s[t])%N; printf("%d ", ans); } int main() { //freopen("test.in", "r", stdin); int T; scanf("%d", &T); for (int times = 0; times < T; ++times) { Work(); } return 0; }