-
Notifications
You must be signed in to change notification settings - Fork 110
/
Copy pathFaulhaber's Formula (Custom Algorithm).cpp
108 lines (90 loc) · 2.66 KB
/
Faulhaber's Formula (Custom Algorithm).cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <bits/stdtr1c++.h>
#define MAX 1010
#define MOD 1000000007
using namespace std;
namespace fool{
#define MAXN 10000
tr1::unordered_map <unsigned long long, int> mp;
int inv, P[MAX], binomial[MAX][MAX], dp[MAXN][MAX];
long long expo(long long x, long long n){
x %= MOD;
long long res = 1;
while (n){
if (n & 1) res = (res * x) % MOD;
x = (x * x) % MOD;
n >>= 1;
}
return (res % MOD);
}
void init(){
int i, j;
mp.clear();
inv = expo(2, MOD - 2);
P[0] = 1;
for (i = 1; i < MAX; i++){
P[i] = (P[i - 1] << 1);
if (P[i] >= MOD) P[i] -= MOD;
}
for (i = 0; i < MAX; i++){
for (j = 0; j <= i; j++){
if (i == j || !j) binomial[i][j] = 1;
else{
binomial[i][j] = (binomial[i - 1][j] + binomial[i - 1][j - 1]);
if (binomial[i][j] >= MOD) binomial[i][j] -= MOD;
}
}
}
for (i = 1; i < MAXN; i++){
long long x = 1;
for (j = 0; j < MAX; j++){
dp[i][j] = dp[i - 1][j] + x;
if (dp[i][j] >= MOD) dp[i][j] -= MOD;
x = (x * i) % MOD;
}
}
}
/// Returns (1^k + 2^k + 3^k + .... n^k) % MOD
long long F(unsigned long long n, int k){
if (n < MAXN) return dp[n][k];
if (n == 1) return 1;
if (n == 2) return (P[k] + 1) % MOD;
if (!k) return (n % MOD);
if (k == 1){
n %= MOD;
return (((n * (n + 1)) % MOD) * inv) % MOD;
}
unsigned long long h = (n << 10LL) | k; /// Change hash function according to limits of n and k
long long res = mp[h];
if (res) return res;
if (n & 1) res = F(n - 1, k) + expo(n, k);
else{
long long m, z;
m = n >> 1;
res = (F(m, k) * P[k]) % MOD;
m--, res++;
for (int i = 0; i <= k; i++){
z = (F(m, i) * binomial[k][i]) % MOD;
z = (z * P[i]) % MOD;
res += z;
}
}
res %= MOD;
return (mp[h] = res);
}
long long faulhaber(unsigned long long n, int k){
///fool::init();
return F(n, k);
}
}
int main(){
fool::init();
int t, i, j;
long long n, k, res;
cin >> t;
while (t--){
cin >> n >> k;
res = fool::faulhaber(n, k);
cout << res << endl;
}
return 0;
}