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;

}

 

你可能感兴趣的:(程序设计)