ACM学习历程—NPU 2015年陕西省程序设计竞赛网络预赛(正式赛)E题 简单题(同余 && 快速幂)
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\n", ans);
}
int main()
{
//freopen("test.in", "r", stdin);
int T;
scanf("%d", &T);
for (int times = 0; times < T; ++times)
{
Work();
}
return 0;
}
把每一道题当作难题去做。
posted on 2015-05-16 20:06 AndyQsmart 阅读(207) 评论(0) 收藏 举报
浙公网安备 33010602011771号