To begin this is a question from SPOJ. I was having some doubts about it.
I would like to know, what is the problem with my approach, which used Binary Exponentiation in 2 steps, the bind function is used to remove the overflow for very large values of A and MOD, and below, is the normal Binary Exponentiation function. How could I solve it?
#define MOD 1000000007ll
using ll long long
ll binAdd(ll a,ll b)
{
ll res=0;
while(b)
{
if(b&1)
res = (res+a) %MOD;
a = (a+a) % MOD;
b>>=1;
}
return res;
}
ll binPow(ll a,ll b)
{
a%=MOD;
ll res=1;
while(b)
{
if(b&1)
res = binAdd(res,a);
a = binAdd(a,a);
b>>=1;
}
return res;
}
ll Z(ll n,ll k)
{
ll s=0;
for(int i=1;i<=n;i++)
s+=binPow(i,k);
for(int i=1;i<=n;i++)
s+=binPow(i,i);
return s;
}
void solve(){
ll n,k;
while(cin >> n >> k && (n!=0 || k!=0))
cout << ((Z(n,k) + Z(n-1,k) - 2LL*Z(n-2,k))) << endl;
}
Input :
10 3
9 31
83 17
5 2
0 0
Expected Output:
4835897
2118762
2285275
3694
Actual Output:
1774843373
1919101650
4154173929
3694
Let's start with the problem statement from the page1 linked by the OP (emphasis mine).
For two given integers n and k find (Zn + Zn-1 - 2Zn-2) mod 10000007, where Zn = Sn + Pn and Sn = 1k + 2k + 3k + … + nk and Pn = 11 + 22 + 33 + … + nn.
...
Constraints
1 < n < 200000000
0 < k < 1000000
The posted attempt has some mistakes that prevents it to produce the expected output
#define MOD 1000000007ll has a typo that makes MOD two orders of magnitude bigger than the required modulo, which is 10'000'007.
using ll long long lacks a = and a ; (typoes, maybe) and even if corrected, it may be confusing.
In Z, the loops have the variable i declared as int, but it goes up to n, which is a long long variable.
The output of solve is the result of the formula Z(n,k) + Z(n-1,k) - 2LL*Z(n-2,k), but that value (all the operations, actually) should be taken modulo MOD.
Once fixed, the algorithm yields the expected results2, but it's still quite inefficient.
The (IMHO wrongly named) function binAdd(a, b) returns the result of (a * b) % MOD without performing a direct multiplication between a and b. This avoids overflowing (and UB) when a > std::numeric_limits<long long>::max() / b (but it still requires std::max(a, res) <= std::numeric_limits<long long>::max() - a at every step).
Given the value of MOD (and the upper limit of n), a 64-bit integer type is wide enough to perform all the needed modular multiplication using the known formula (A * B) mod C = (A mod C * B mod C) mod C without overflowing.
Note that this is also the reason why the loops in OP's Z function can accumulate all those sums without overflowing.
There's no need to loop linearly up to n:
Zn + Zn-1 - 2Zn-2 = Sn + Sn-1 - 2Sn-2 + Pn + Pn-1 - 2Pn-2
= 1k + 2k + 3k + … + (n - 2)k + (n - 1)k + nk
+ 1k + 2k + 3k + … + (n - 2)k + (n - 1)k
- (1k + 2k + 3k + … + (n - 2)k) * 2
+ 11 + 22 + 33 + … + (n - 2)n-2 + (n - 1)n-1 + nn
+ 11 + 22 + 33 + … + (n - 2)n-2 + (n - 1)n-1
- (11 + 22 + 33 + … + (n - 2)n-2) * 2 =
= 2((n - 1)k + (n - 1)n-1) + nk + nn
This leads to an O(log(max(n,k)) algorithm3.
1) https://www.spoj.com/problems/ZSUM/
2) https://godbolt.org/z/8sbo7Whxd
3) https://godbolt.org/z/bnsz94cf5
Related
I Have this formula:
(n - 1)! ((n (n - 1))/2 + ((n - 1) (n - 2))/4)
2<=n<=100000
I would like to modulate the result of this from this formula by any modulo, but for the moment let's assume that it is constant, MOD = 999999997. Unfortunately I can't just calculate the result and modulate it, because unfortunately I don't have variables larger than 2^64 at my disposal, so the main question is. What factors to modulate by MOD to get the results%MOD ?
Now let's assume that n=19. What is in brackets is equal to 247.5
18! = 6402373705728000.
(6402373705728000 * 247.5)mod999999997 = 921442488.
Unfortunately, in case I modulate 18! first, the result will be wrong, because (18!)mod999999997 = 724935119. (724935119 * 247.5)mod9999997 = 421442490.
How to solve this problem?
I think the sum could be break down. The only tricky part here is that (n - 1)(n - 2)/4 may have a .5 decimal., as n(n-1) / 2 will always be integer.
S = (n - 1)! * ((n (n - 1))/2 + ((n - 1) (n - 2))/4)
= [(n-1)! * (n*(n-1)/2)] + [(n-1)! * (n-1)(n-2)/4]
= A + B
A is easy to do. With B, if (n-1)(n-2) % 4 == 0 then there's nothing else either, else you can simplified to X/2, as (n-1)(n-2) is also divisible by 2.
If n = 2, it's trivial, else if n > 2 there's always a 2 in the representation of (N-1)! = 1x2x3x ... xN. In that case, simply calculate ((N-1)!/2) = 1x3x4x5x ... xN.
Late example:
N = 19
MOD = 999999997
--> 18! % MOD = 724935119 (1)
(18!/2) % MOD = 862467558 (2)
n(n-1)/2 = 171 (3)
(n-1)(n-2)/2 = 153 (4)
--> S = (1)*(3) + (2)*(4) = 255921441723
S % MOD = 921442488
On another note, if mod is some prime number, like 1e9+7, you can just apply Fermat's little theorem to calculate multiplicative inverse as such:
(a/b) % P = [(a%P) * ((b^(P-2)) % P)] % P (with P as prime, a and b are co-prime to P)
You will have to use 2 mathematical formulas here:
(a + b) mod c == (a mod c + b mod c) mod c
and
(a * b) mod c == (a mod c * b mod c) mod c
But those are only valid for integers. The nice part here is that formula can only be integer for n >= 2, provided you compute it as:
(((n - 1)! * n * (n - 1))/2) + (((n - 1)! * (n - 1) * (n - 2))/4)
1st part is integer | 2nd part is too
for n == 2, first part boils down to 1 and second is 0
for n > 2 either n or n-1 is even so first part is integer, and again eithe n-1 of n-2 is even and (n-1)! is also even so second part is integer. As your formula can be rewritten to only use additions and multiplications it can be computed.
Here is a possible C++ code (before unsigned long long is required):
#include <iostream>
template<class T>
class Modop {
T mod;
public:
Modop(T mod) : mod(mod) {}
T add(T a, T b) {
return ((a % mod) + (b % mod)) % mod;
}
T mul(T a, T b) {
return ((a % mod) * (b % mod)) % mod;
}
int fact_2(T n) {
T cr = 1;
for (T i = 3; i <= n; ++i) {
cr = mul(cr, i);
}
return cr;
}
};
template<class T>
T formula(T n, T mod) {
Modop<T> op = mod;
if (n == 2) {
return 1;
}
T second, first = op.mul(op.fact_2(n - 1), op.mul(n, n - 1));
if (n % 2 == 0) {
second = op.mul(op.fact_2(n - 1), op.mul((n - 2)/ 2, n - 1));
}
else {
second = op.mul(op.fact_2(n - 1), op.mul(n- 2, (n - 1) / 2));
}
return op.add(first, second);
}
int main() {
std::cout << formula(19ull, 999999997ull) << std::endl;
return 0;
}
First of All , for n=2 we can say that the result is 1.
Then, the expression is equal to: (n*(n-1)(n-1)!)/2 + (((n-1)(n-2)/2)^2)*(n-3)! .
lemma: For every two consecutive integer number , one of them is even.
By lemma we can understand that n*(n-1) is even and also (n-1)*(n-2) is even too. So we know that the answer is an integer number.
First we calculate (n*(n-1)(n-1)!)/2 modulo MOD. We can calculate (n(n-1))/2 that can be saved in a long long variable like x, and we get the mod of it modulo MOD:
x = (n*(n-1))/2;
x %= MOD;
After that for: i (n-1 -> 1) we do:
x = (x*i)%MOD;
And we know that both of 'x' and 'i' are less than MOD and the result of
multiplication can be save in a long long variable.
And likewise we do the same for (((n-1)(n-2)/2)^2)(n-3)! .
We calculate (n-1)*(n-2)/2 that can be save in a long long variable like y, and we get the mod of it modulo MOD:
y = ((n-1)*(n-2))/2;
y %= MOD;
And after that we replace (y^2)%MOD on y because we know that y is less than MOD and y*y can be save in a long long variable:
y = (y*y)%MOD;
Then like before for: i (n-3 -> 1) we do:
y = (y*i)%MOD;
And finally the answer is (x+y)%MOD
I'm stuck determining the big o notation for the below fragmented code, the given expression is part of I'm trying to figure out. I know given two plain, default for loops results in O(n^2) but the latter is entirely different. Here are the instructions.
The algorithm of
for (j = 0; j < n; j++)
{
for (k = j; k < n; k++)
{
}
}
will result in a number of iterations of given by the expression:
= n + (n-1) + (n-2) + (n-3) + ........ + (n - n)
Reduce the above series expression to an algebraic expression, without summation.
After determining the algebraic expression express the performance in Big O Notation.
You can use this method (supposedly applied by Gauss when he was a wee lad).
If you sum all the numbers twice, you have
1 + 2 + 3 + ... + n
+ n + (n-1) + (n-2) + ... + 1
—————————————————————————————————————--
(n+1) + (n+1) + (n+1) + ... + (n+1) = n(n+1)
Thus,
1 + 2 + 3 + ... + n = n(n+1)/2
and n(n+1)/2 is (n^2)/2 + n/2, so it is in O(n^2).
There are 3 numbers: T, N, M. 1 ≤ T, M ≤ 10^9, 1 ≤ N ≤ 10^18 .
What is asked in the problem is to compute [Σ(T^i)]mod(m) where i varies from 0 to n. Obviously, O(N) or O(M) solutions wouldn't work because of 1 second time limit. How should I proceed?
As pointed out in previous answers, you may use the formula for geometric progression sum. However there is a small problem - if m is not prime, computing (T^n - 1) / (T - 1) can not be done directly - the division will not be a well-defined operations. In fact there is a solution that can handle even non prime modules and will have a complexity O(log(n) * log(n)). The approach is similar to binary exponentiation. Here is my code written in c++ for this(note that my solution uses binary exponentiation internally):
typedef long long ll;
ll binary_exponent(ll x, ll y, ll mod) {
ll res = 1;
ll p = x;
while (y) {
if (y % 2) {
res = (res * p) % mod;
}
p = (p * p) % mod;
y /= 2;
}
return res;
}
ll gp_sum(ll a, int n, ll mod) {
ll A = 1;
int num = 0;
ll res = 0;
ll degree = 1;
while (n) {
if (n & (1 << num)) {
n &= (~(1 << num));
res = (res + (A * binary_exponent(a, n, mod)) % mod) % mod;
}
A = (A + (A * binary_exponent(a, degree, mod)) % mod) % mod;
degree *= 2;
num++;
}
return res;
}
In this solution A stores consecutively the values 1, 1 + a, 1 + a + a^2 + a^3, ...1 + a + a^2 + ... a ^ (2^n - 1).
Also just like in binary exponentiation if I want to compute the sum of n degrees of a, I split n to sum of powers of two(essentially using the binary representation of n). Now having the above sequence of values for A, I choose the appropriate lengths(the ones that correspond to 1 bits of the binary representation of n) and multiply the sum by some value of a accumulating the result in res. Computing the values of A will take O(log(n)) time and for each value I may have to compute a degree of a which will result in another O(log(n)) - thus overall we have O(log(n) * log (n)).
Let's take an example - we want to compute 1 + a + a^2 .... + a ^ 10. In this case, we call gp_sum(a, 11, mod).
On the first iteration n & (1 << 0) is not zero as the first bit of 11(1011(2)) is 1. Thus I turn off this bit setting n to 10 and I accumulate in res: 0 + 1 * (a ^ (10)) = a^10. A is now a + 1.
The next second bit is also set in 10(1010(2)), so now n becomes 8 and res is a^10 + (a + 1)*(a^8)=a^10 + a^9 + a^8. A is now 1 + a + a^2 + a^3
Next bit is 0, thus res stays the same, but A will become 1 + a + a^2 + ... a^7.
On the last iteration the bit is 1 so we have:
res = a^10 + a^9 + a^8 + a^0 *(1 + a + a^2 + ... +a^7) = 1 + a .... + a ^10.
One can use an algorithm which is similar to binary exponentiation:
// Returns a pair <t^n mod m, sum of t^0..t^n mod m>,
// I assume that int is big enough to hold all values without overflowing.
pair<int, int> calc(int t, int n, int m)
if n == 0 // Base case. t^0 is always 1.
return (1 % m, 1 % m)
if n % 2 == 1
// We just compute the result for n - 1 and then add t^n.
(prevPow, prevSum) = calc(t, n - 1, m)
curPow = prevPow * t % m
curSum = (prevSum + curPow) % m
return (curPow, curSum)
// If n is even, we compute the sum for the first half.
(halfPow, halfSum) = calc(t, n / 2, m)
curPow = halfPow * halfPow % m // t^n = (t^(n/2))^2
curSum = (halfSum * halfPow + halfSum) % m
return (curPow, curSum)
The time complexity is O(log n)(the analysis is the same as for the binary exponentiation algorithm). Why is it better than a closed form formula for geometric progression? The latter involves division by (t - 1). But it is not guaranteed that there is an inverse of t - 1 mod m.
you can use this:
a^1 + a^2 + ... + a^n = a(1-a^n) / (1-a)
so, you just need to calc:
a * (1 - a^n) / (1 - a) mod M
and you can find O(logN) way to calc a^n mod M
It's a geometric series whose sum is equal to :
i am working on an algorithm and want to make my code more efficient.my code uses simple arithmetic and comparison statements.however,i want to replace if statements,as they could be time consuming.this code would be run over a million times,so even the slightest improvement is appreciated.please answer!here is the code-
int_1024 sqcalc(int_1024 s,int_1024 f){
f=f*20;
s=s-81;
s=s-(f*9);
if(s>=0){
return 9;
}
s=s+f;
s=s+17;
if(s>=0){
return 8;
}
s=s+f;
s=s+15;
if(s>=0){
return 7;
}
s=s+f;
s=s+13;
if(s>=0){
return 6;
}
s=s+f;
s=s+11;
if(s>=0){
return 5;
}
s=s+f;
s=s+9;
if(s>=0){
return 4;
}
s=s+f;
s=s+7;
if(s>=0){
return 3;
}
s=s+f;
s=s+5;
if(s>=0){
return 2;
}
s=s+f;
s=s+3;
if(s>=0){
return 1;
}
s=s+f;
s=s+1;
if(s>=0){
return 0;
}
}
i wish to replace if checks,since i 'think' they make the algorithm slow.any suggestions?int_1024 is a ttmath variable with 1000's of bits,so saving on it might be a good option?division or multiplication for such a large number might be slow,so i tried using addition,but to no avail.help please.
I don't know if it is any faster, but it is considerably shorter (and easier to analyze).
int k[] = { 17, 15, 13, 11, 9, 7, 5, 3, 1 };
int r = 0;
f *= 20;
s -= 81;
s -= f * 9;
while (s < 0) {
s += f;
s += k[r];
if (++r == 9) break;
}
if (s >= 0) return 9-r;
Edit:
In fact, the original poster came up with a clever way to optimize this loop by pre-computing the sum of constants in the k array, and compared s against the sums, rather than incrementally adding them to s.
Edit:
I followed moonshadow's analysis technique, but arrived at a different equation. Original TeX formatting replaced with ASCII art (I tried to get MathJax to render the TeX for me, but it wasn't working):
S[0] = s >= 0 => 9 - 0
S[1] = S[0] + f + 19 - 2*1 >= 0 => 9 - 1
S[2] = S[1] + f + 19 - 2*2 >= 0 => 9 - 2
...
S[i] = S[i-1] + f + 19 - 2*i >= 0 => 9 - i
So to calculate S[n]:
S[n] = S[n-1] + f + 19 - 2n
.-- n
=> S[n] = s + > (f + 19 - 2*i)
`-- i=1 .-- n
=> S[n] = s + n(f + 19) - 2 > i
`-- i=1
=> S[n] = s + n(f + 19) - n(n+1)
2
=> S[n] = s + n(f + 18) - n
So, the inequality S[n] >= 0 is a quadratic equation in n. Assuming s < 0, we want n to be the ceiling of the solution to the quadratic.
+-- --+
| _____________ |
| / 2 |
| f + 18 - . / (f + 18) + 4s |
| ` |
n = | --------------------------- |
| 2 |
So the routine would look something like:
f *= 180;
s -= 81;
s -= f;
if (s >= 0) return 9;
f /= 9;
f += 18;
s *= 4;
int1024_t ff = f;
ff *= f;
ff += s;
ff = ff.Sqrt();
f -= ff;
f += f.Mod2();
return 9 - f/2;
However, I am not sure the expense of performing these operations on your big integer objects is worth implementing to replace the simple loop shown above. (Unless you expect to extend the function and would require a much longer loop.)
To be faster than the loop, the big integer square root implementation would have to always converge within 4 iterations to beat the average expected 4.5 iterations of the existing while loop. However the ttmath implementation does not seem to be calculating an integer square root. It seems to calculate a floating point square root and then rounding the result, which I would guess would be much slower than the loop.
First of all, I note that if the condition of the final if() is false, the return value is undefined. You probably want to fix that.
Now, the function starts with
f=f*20;
s=s-81;
s=s-(f*9);
if(s>=0){
return 9;
}
and the rest looks incredibly repetitive. Let's see if we can use that repetition. Let's build a table of inequalities - values of s vs the eventual result:
s + (f+17) >= 0: 8
s + (f+17) + (f+15) >= 0: 7
s + (f+17) + (f+15) + (f+13) >= 0: 6
.
.
s + (f+17) + (f+15) + (f+13) + ... + (f+1) >= 0: 0
So, each line tests to see if s + some multiple of f + some constant is greater than 0. The value returned, the constant and the multiple of f all look related. Let's try expressing the relationship:
(s + ((9-n)*f) + (2*n)-1 >= 0)
Let's rearrange that so n is on one side.
(s + (9*f) - (n*f) + (2*n)-1 >= 0)
(s + (9*f) +1 >= (n*f) - (2*n))
(s + (9*f) +1 >= n*(f - 2))
n <= ((s + (9*f) +1) / (f - 2)
Now, the function has a range of return values for different inputs. In fact, we are interested in values of n in the range 0..8: the function supplied is undefined for inputs that would yield n < 0 (see above). The preamble ensures we never see inputs that would yield n > 8.
So we can just say
int_1024 sqcalc(int_1024 s,int_1024 f){
f=f*20;
s=s-81;
s=s-(f*9);
if(s>=0){
return 9;
}
return (s + (9*f) +1) / (f - 2);
}
and for all cases where the result is not undefined, the behaviour should be the same as the old version, without needing tons of conditionals or a loop.
Demonstration of accuracy is at http://ideone.com/UzMZs.
According to the OP's comment, the function is trying to find all values that satisfy the inequality:
N * ((20 * F) + N) <= S
For all N, given an F and S.
Using algebra, this comes out to:
1) N^2 + 20Fn - S <= 0 (where N^2 is N*N or sqr(N))
The OP should use some constants for F and N and solve algebraically (sp?) or search the web for "C++ find root quadratic equation".
One a function is selected, then profile the function and optimize if necessary.
i tried solving the quadratics,and it makes the function slower for larger digits.following the answer by #user315052,i made this code.
int_1024 sqcalc(int_1024 s,int_1024 f){
int k[] = { 0, 17, 32, 45, 56, 65, 72, 77, 80, 81 };
f=f*20;
s=((f*9)+81)-s;
int i=0;
while(s>k[i]){
s-=f;
i++;
}
return 9-i;
}
in this code,instead of subtracting a number and then comparing with zero,i directly compare it with the number.by far,this produces the fastest results.i could do binary search though....
I have the compute the sum S = (a*x + b*y + c) % N. Yes it looks like a quadratic equation but it is not because the x and y have some properties and have to be calculated using some recurrence relations. Because the sum exceeds even the limits of unsigned long long I want to know how could I compute that sum using the properties of the modulo operation, properties that allow the writing of the sum something like that(I say something because I do not remember exactly how are those properties): (a*x)%N + (b*y)%N + c%N, thus avoiding exceeding the limits of unsigned long long.
Thanks in advance for your concern! :)
a % N = x means that for some integers 0 <= x < N and m: m * N + x = a.
You can simply deduce then that if a % N = x and b % N = y then
(a + b) % N =
= (m * N + x + l * N + y) % N =
= ((m + l) * N + x + y) % N =
= (x + y) % N =
= (a % N + b % N) % N.
We know that 0 < x + y < 2N, that is why you need to keep remainder calculation. This shows that it is okay to split the summation and calculate the remainders separately and then add them, but don't forget to get the remainder for the sum.
For multiplication:
(a * b) % N =
= ((m * N + x) * (l * N + y)) % N =
= ((m * l + x * l + m * y) * N + x * y) % N =
= (x * y) % N =
= ((a % N) * (b % N)) % N.
Thus you can also do the same with products.
These properties can be simply derived in a more general setting using some abstract algebra (the remainders form a factor ring Z/nZ).
You can take the idea even further, if needed:
S = ( (a%N)*(x%N)+(b%N)*(y%N)+c%N )%N
You can apply the modulus to each term of the sum as you've suggested; but even so after summing them you must apply the modulus again to get your final result.
How about this:
int x = (7 + 7 + 7) % 10;
int y = (7 % 10 + 7 % 10 + 7 % 10) % 10;
You remember right. The equation you gave, where you %N every of the summands is correct. And that would be exactly what I use. You should also %N for every partial sum (and the total) again, as the addition results can be still greater than N. BUT be careful this works only if your size limit is at least twice as big as your N. If this is not the case, it can get really nasty.
Btw for the following %N operations of the partial sums, you dont have to perform a complete division, a check > N and if bigger just subtraction of N is enough.
Not only can you reduce all variable mod n before starting the calculation, you can write your own mod-mul to compute a*x mod n by using a shift-and-add method and reduce the result mod n at each step. That way your intermediate calculations will only require one more bit than n. Once these products are computed, you can add them pairwise and reduce mod n after each addition which will also not require more than 1 bit beyond the range of n.
There is a python implementation of modular multiplication in my answer to this question. Conversion to C should be trivial.