题意:
给定两个数
n
n
n和
k
k
k,求
∑
i
=
1
n
i
k
m
o
d
10007
\sum_{i=1}^ni^k\ mod\ 10007
∑i=1nik mod 10007的值
题解:
容易发现直接暴力枚举的时间复杂度是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),而
n
n
n的数据范围比较大,因此暴力不行。
我们可以考虑到,这里的模数10007比较小,因此,我们可以从每个数模10007的余数下手。利用这个同余,我们发现
1
k
,
1000
8
k
,
2001
5
k
,
…
%
10007
1^k,10008^k,20015^k,\dots\%10007
1k,10008k,20015k,…%10007的值是相等的。可以发现,每隔10007个数就会出现一个同余的数,可以得到证明。因此,我们这里可以直接枚举余数,然后找出每个余数出现次数即可得到最后的答案。
实现细节见代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(ll a, ll b) {
ll ans = 1;
while (b) {
if (b & 1) {
ans = (ans * a) % 10007;
}
a = (a * a) % 10007;
b >>= 1;
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
ll n, k;
cin >> n >> k;
ll ans = 0;
for (ll i = 1; i <= min(n, (ll)10007); i++) { // 枚举可能的余数
ans = (ans + qpow(i, k) * ((n - i) / (ll)10007 + 1)) % 10007; // 找到该余数对应的出现次数
}
cout << ans << endl;
}
return 0;
}