Number sequence program speed - c++

I have this number sequence - xm = y.xm-1 + z (mod 20 000).
These are the restrictions:
1 ≤ x < 20 000,
0 ≤ y, z ≤ 9,
1 ≤ N ≤ 2 000 000 00
And here is my [code][1].
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
double k =0;
int x,y,z;
unsigned long long n;
int solve()
{
int result = 0;
int prevX = x;
for(unsigned long long i =1; i<n; i++)
{
if(result<20000)
{
result = y * prevX+z;
prevX = result;
}
else
{
result = y * prevX+z;
result = result % 20000;
prevX = result;
}
}
return result;
}
int main()
{
int tests =0;
cin >> tests;
cin.ignore();
while(tests--)
{
scanf("%d %d %d %Ld", &x, &y, &z, &n);
int result = solve();
cout << result;
}
}
Example input:
1
2 3 4 10
Example output:
18730
Details:
1 on the first row is the number of input test.
2 3 4 10 - x,y,z, N;
The judging system that I'm using is giving me a time limit error. So my program is slow.
Is there any way to predict this number sequence, elimanating most of the cycles?

Your solution is linear, because you have a loop from 0 to N. You can do logarithmic instead.
You can get to the equation empirically, with a simple experiment, just plug in a number, like m = 4. Let's ignore the modulo part for the moment because we can just do this on the final number (see for example https://en.wikipedia.org/wiki/Modular_arithmetic#Integers_modulo_n).
x[4] = y * x[3] + z
= y * (y * x[2] + z) + z
= y^2 * x[2] + y * z + z
= y^2 * (y * x[1] + z) + y * z + z
= y^3 * x[1] + y^2 * z + y * z + z
So you can easily get the rule, if you don't, start with m = 5. It is:
x[m] = y^(m-1) * x[1] + y^(m-2) * z + ... + y^0 * z
= y^(m-1) * x[1] + z * (y^(m-2) + ... + y^0)
Observe, that this is a geometric series, i.e.
x[m] = y^(m-1) * x[1] + z * (y^(m-1) - 1) / (y - 1) mod 20000
So what remains is to calculate y^(m-1), which you can do in log m easily.
In all steps be aware of the modulo rules! I.e., if you calculate y * y mod 20000, calculate (y mod 20000) * (y mod 20000) mod 20000 instead.
Example
Let's take z = 10, y = 11, x[1] = 3, then you have
x[2] = 11 * 3 + 10 mod 20000 = 43
x[3] = 11 * 43 + 10 mod 20000 = 483
x[4] = 11 * 1850 + 10 mod 20000 = 5323
x[5] = 11 * 460 + 10 mod 20000 = 58563 mod 20000 = 18563
Or you can get it directly:
x[5] = 11^4 * 3 + 10 * (11^4 - 1) / (11 - 1) mod 20000
= 14641 * 3 + 10 * (14641 - 1) / 10 mod 20000
= 43923 + 14640 mod 20000
= 644204 mod 20000
= 18563
Remember that if y == 19284, you calculate the fourth power as (y^2 mod 20000)^2 mod 20000 = 12656^2 mod 20000 = 14336 to ensure that you don't get overflows.

Related

Why is C++ not changing my code's numbers' condition according to pow (-1,i)?

I have C++ code here:
#include <iostream>
#include <cmath>
#include <time.h>
using namespace std;
int main()
{
double n,x;
cin>>n>>x;
double b=1,c=0.0;
for (int i=1;i<=n;i++){
x=pow(x,i);
x=x*pow((-1),(i+1));
cout<<x<<endl;
b=i;
c=c+x/b;
}
cout<<c<<endl;
return 0;
}
I am creating this to calculate x^1-x^2/2+x^3/3-.....+(-1)^(n-1)*(x^n)/n. The user inputs n. The problem appears to be in this line: x=x*pow((-1),(i+1));.
I am creating this to calculate x^1 - x^2/2 + x^3/3 - ... + (-1)^(n-1)*(x^n)/n.
That seems to be the Maclaurin series of ln(1 + x), but it's not what the posted code evaluates, though:
for (int i=1;i<=n;i++)
{
x = pow(x,i);
// ^ This is updated at each iteration! It should be const.
x = x * pow((-1),(i+1));
// ^^^^^^^^^^^^^^^ Please don't (see later).
b=i;
c=c+x/b;
// ^ Okish, but why not use i directly?
}
At the very least, a variable different from x should be introduced to store the results of the powers.
The use of pow((-1),(i+1)) to generate the simple sequence {1, -1, 1, -1, ...} is also questionable, if not prone to rounding errors. I'll show two different ways to accomplish the same task.
// Evaluates the Mclaurin series of ln(1 + x) using n terms.
// Noting that (e.g. with n == 4):
// p(4) = x -x^2 / 2 + x^3 / 3 - x^4 / 4
// p(4) = x - x*x/2 + x*x*x/3 - x*x*x*x/4
// p(4) = k(1) -x*k(1)/2 + x*x*x/3 - x*x*x*x/4 k(1) = x
// p(4) = k(1) -x*k(1)/2 -x*k(2)/3 - x*x*x*x/4 k(2) = -x*k(1)
// p(4) = k(1) -x*k(1)/2 -x*k(2)/3 -x*k(3)/4 k(3) = -x*k(2)
// Preconditions: n >= 1 and -1 < x <= 1
double fn(int n, double x)
{
double k{ x };
double sum{ x };
for (int i{ 2 }; i <= n; ++i)
{
k *= -x;
sum += k / i;
}
return sum;
}
Note that, in the interval of convergence, abs(k / i) tends to zero, while outside it grows. Eventually, due to the limited precision of floating-point types like double, sum += k/i won't change the value of sum.
Another approach may be based on Horner's rule.
// Evaluates the Mclaurin series of ln(1 + x) using n terms.
// Applying Horner's rule:
// p(4) = x -x^2 / 2 + x^3 / 3 - x^4 / 4
// = x*(1 + x*(-1/2 + x*(1/3 + x*(-1/4))))
// = x*(1 + x*(-1/2 + x*( 1/3 + x*k(4) ))) k(4) = 1/4
// = x*(1 + x*( -1/2 + x*k(3) )) k(3) = 1/3 + x*k(4)
// = x*( 1 + x*k(2) ) k(2) = -1/2 + x*k(3)
// = x * k(1) k(1) = 1 + x*k(2)
// Preconditions: n >= 1 and -1 < x <= 1
double fn(int n, double x)
{
double sign{ n % 2 == 0? -1.0 : 1.0 };
double k{ sign / n };
while ( --n > 0 )
{
sign = -sign;
k = sign / n + x * k;
}
return k * x;
}

Count the value of 2d Matrix

I need to count the value of the matrix. Let's see the example, because its bit hard to explain.
There is a 2d quadratic matrix ( rows == columns ) let's called it int n and it must be odd ( 3x3, 5x5, 7x7,.. ) and we have int x. We need to find the sum of the value based on x. The value of x is start from 0 and less than n/2.
Example:
Matrix 3x3
1 1 1
2 2 2
3 3 3
if x is 0, we need to sum 1 + 1 + 1 + 2 + 2 + 3 + 3 + 3 = 16.
if x is 1, output is 2.
x cant be more than 1, because 2 > n/2.
Matrix 5x5
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
2 2 2 2 2
1 1 1 1 1
if x is 0, then output will be 24 ( 1 + 1 + 1 + 1 + 1 + 2 + 2 + 3 + 3 + 2 + 2 + 1 + 1 + 1 + 1 + 1 )
if x is 1, then output will be 18 ( 2 + 2 + 2 + 3 + 3 + 2 + 2 + 2 )
if x is 2, then output will be 3.
as you can see, the bold number is if x is 0, and the italic number is if x is 1.
Then, i came up with this code
int test( int A[100][100], int n, int x){
if( x == ( n - 1 ) / 2 )
return A[((n-1)/2)][((n-1)/2)];
if(x >= 0 && x < ( n - 1 )/2 )
return A[((n-1)/2)-x-1][((n-1)/2)-x-1] + A[((n-1)/2)-x-1][((n-1)/2)] + A[((n-1)/2)-x-1][((n-1)/2)+x+1] + A[((n-1)/2)][((n-1)/2)-x-1] + A[((n-1)/2)][((n-1)/2)+x+1]
+ A[((n-1)/2)+x+1][((n-1)/2)-x-1] + A[((n-1)/2)+x+1][((n-1)/2)] + A[((n-1)/2)+x+1][((n-1)/2)+x+1];
}
The problem is, if the matrix is only 3x3, its ok. but if the matrix is greater than 3x3 will come up with wrong output.
Also, I tried with loop. but didn't work.
int test(int A[100][100], int n, int x ) {
for ( int i = 0; i < n; i ++ ) {
for ( int j = 0; j < n; j ++ ) {
int count = 0;
if ( i < n - 1 ) // bottom
count = count + A[((n-1)/2)+1+x][(n-1)/2];
if ( j < n - 1 ) // right
count = count + A[(n-1)/2][((n-1)/2)+1+x];
if ( j >= 1 ) // left
count = count + A[(n-1)/2][((n-1)/2)-1-x];
if ( i >= 1 ) // top
count = count + A[((n-1)/2)-1-x][(n-1)/2];
if ( j >= 1 && i >= 1 ) // left top
count = count + A[((n-1)/2)-1-x][((n-1)/2)-1-x];
if ( j < n - 1 && i >= 1 ) // right top
count = count + A[((n-1)/2)-1-x][((n-1)/2)+1+x];
if ( j >= 1 && i < n - 1 ) // left bottom
count = count + A[((n-1)/2)+1+x][((n-1)/2)-1-x];
if ( j < n - 1 && i < n - 1 ) // right bottom
count = count + A[((n-1)/2)+1+x][((n-1)/2)+1+x];
return count;
}
}
}
You want to sum up a ring. You only need one loop, not two nested loops:
It doesn't make sense to unconditionally return in a loop. It will break out of the loop in the first iteration. You should return after the loop.
It doesn't make sense to initialize count in the loop. It will reset it in each iteration. You should initialize count before the loop.
You don't use the loop variables in your calculation. You should access different elements using i and j.
You can make your life easier if you set the loop to
int test(int A[100][100], int n, int x) {
int count = 0;
for (int i = x; i < n - x - 1; ++i) {
count += A[i][x];
count += A[i + 1][n - x - 1];
count += A[x][i];
count += A[n - x - 1][i + 1];
}
return count;
}
or use std::accumulate
int test(int A[100][100], int n, int x) {
return std::accumulate(A[x] + x, A[x] + n - x - 1, 0)
+ std::accumulate(A[n - x - 1] + x + 1, A[n - x - 1] + n - x, 0)
+ std::accumulate(A + x + 1, A + n - x, 0, [x, n](auto acc, auto el) {
return acc + el[x];
})
+ std::accumulate(A + x, A + n - x - 1, 0, [x, n](auto acc, auto el) {
return acc + el[n - x - 1];
});
}
It's unclear for me why you need parameter n. A has a fixed size 100x100. n has to be 100. You could rewrite both codes to
constexpr int n = 100;
int test(int A[n][n], int x) {
int count = 0;
for (int i = x; i < n - x - 1; ++i) {
count += A[i][x];
count += A[i + 1][n - x - 1];
count += A[x][i];
count += A[n - x - 1][i + 1];
}
return count;
}
resp.
constexpr int n = 100;
int test(int A[n][n], int x) {
return std::accumulate(A[x] + x, A[x] + n - x - 1, 0)
+ std::accumulate(A[n - x - 1] + x + 1, A[n - x - 1] + n - x, 0)
+ std::accumulate(A + x + 1, A + n - x, 0, [x](auto acc, auto el) {
return acc + el[x];
})
+ std::accumulate(A + x, A + n - x - 1, 0, [x](auto acc, auto el) {
return acc + el[n - x - 1];
});
}
or using templates
template<int n>
int test(int A[n][n], int x) {
int count = 0;
for (int i = x; i < n - x - 1; ++i) {
count += A[i][x];
count += A[i + 1][n - x - 1];
count += A[x][i];
count += A[n - x - 1][i + 1];
}
return count;
}
resp.
template<int n>
int test(int A[n][n], int x) {
return std::accumulate(A[x] + x, A[x] + n - x - 1, 0)
+ std::accumulate(A[n - x - 1] + x + 1, A[n - x - 1] + n - x, 0)
+ std::accumulate(A + x + 1, A + n - x, 0, [x](auto acc, auto el) {
return acc + el[x];
})
+ std::accumulate(A + x, A + n - x - 1, 0, [x](auto acc, auto el) {
return acc + el[n - x - 1];
});
}
template <int N>
int SumRing (const int A[N][N], const int x)
{
// x represents the lower end, XX the upper:
const int XX = N - x - 1;
// special case: no "ring", only middle element:
if (x == XX)
return A[x][x];
// edges of the ring:
const int r_top = x;
const int c_left = x;
const int r_bottom = XX;
const int c_right = XX;
// We add clockwise around the ring,
// each time leaving out the last element
// to avoid its double-count:
int sum = 0;
// top row:
for (int c = c_left; c < c_right; ++c)
sum += A[r_top][c];
// right column:
for (int r = r_top; r < r_bottom; ++r)
sum += A[r][c_right];
// bottom row:
for (int c = c_right; c > c_left; --c)
sum += A[r_bottom][c];
// left column:
for (int r = r_bottom; r > r_top; --r)
sum += A[r][c_left];
return sum;
}
If you don't know the array size before run-time, then you may want to consider a matrix wrapper class around std::vector.

nested for loop optimisation

I have this expression
for (size_t i = 0; i < expression.size(); i++){
for (size_t j = i + 1; j < expression.size(); j++){
result += (expression.at(j) - expression.at(i));
}
result += (g - expression.at(i));
}
return result;
in the vector expression we have for example [1,2,3]. I am trying to get something like:
f1=[(2-1)+(3-1)]
r1 = g-1
h1 = r1+f1
f2=[3-2]
r2 = g-2
h2 = r2+f2
f3 = 0
r3 = g-3
h3 = r3+f3
then h1+h2+h3
What i am doing right now is in Θ(n^2). Is there a way to make it faster even without for loops?
Addition is commutative and associative so the operations can be reordered and grouped without changing the final result. (Note: not taking into account possible overflows in the intermediate calculations, which may be affected by the order and grouping of operations.)
In pseudo-code with n = expression.size() and x[k] = expression.at(k) the original code can be broken down as follows, with the intermediate results indicated in comments.
a = b = c = d = 0
for i = 0 to (n-1)
for j = (i+1) to (n-1)
a += x[j]
// == x[i+1] + x[i+2] + ... x[n-1]
// a == 0 * x[0] + 1 * x[1] + 2 * x[2] + 3 * x[3] + ... + (n-1) * x[n-1]
for i = 0 to (n-1)
for j = (i+1) to (n-1)
b += x[i];
// == (n-i-1) * x[i]
// b == (n-1) * x[0] + (n-2) * x[1] + ... + 2 * x[n-3] + 1 * x[n-2]
for i = 0 to (n-1)
c += g
// c == n * g
for i = 0 to (n-1)
d += expression.at(i))
// d == x[0] + x[1] + ... + x[n-1]
result = c + a - b - d
= n * g
+ (0 - (n-1) - 1) * x[0]
+ (1 - (n-2) - 1) * x[1]
+ ...
+ ((n-2) - 1 - 1) * x[n-2]
+ ((n-1) - 0 - 1) * x[n-1]
The latter result can be calculated directly from that formula, with one single O(n) loop.

Find the value of polynomial at some K different integers, modulo 786433

You are given a polynomial of degree N with integer coefficients. Your task is to find the value of this polynomial at some K different integers, modulo 786433.
Input
The first line of the input contains an integer N denoting the degree of the polynomial.
The following line of each test case contains (N+1) integers denoting the coefficients of the polynomial. The ith numbers in this line denotes the coefficient a_(i-1) in the polynomial a_0 + a_1 × x_1 + a_2 × x_2 + ... + a_N × x_N.
The following line contains a single integer Q denoting the number of queries.
The jth of the following Q lines contains an integer number x_j denoting the query.
Output
For each query, output a single line containing the answer to the corresponding query. In other words, the jth line of the output should have an integer equal to a_0 + a_1 × x_j + a_2 × x_j^2 + ... + a_N × x_j^N modulo 786433.
Constraints and Subtasks
0 ≤ a_i, x_j < 786433
Subtask #1 (37 points): 0 ≤ N, Q ≤ 1000
Subtask #2 (63 points): 0 ≤ N, Q ≤ 2.5 × 10^5
Example
Input:
2
1 2 3
3
7
8
9
Output:
162
209
262
Explanation
Example case 1.
Query 1: 1 + 2 × 7 + 3 × 7 × 7 = 162
Query 2: 1 + 2 × 8 + 3 × 8 × 8 = 209
Query 3: 1 + 2 × 9 + 3 × 9 × 9 = 262
Here is the code that runs in O(n log n) time. I use Fast Fourier Transform to multiply the two polynomials.
Why do I need to use the modulo 786433 operator for all calculations? I understand that this might relate to int overflow? It this normal in competitive programming questions?
#include <cstdio>
#include <algorithm>
#include <vector>
#include <sstream>
#include <iostream>
using namespace std;
#define all(a) (a).begin(),(a).end()
#define pb push_back
#define sz(a) ((int)(a).size())
#define mp make_pair
#define fi first
#define se second
typedef pair<int, int> pint;
typedef long long ll;
typedef vector<int> vi;
#define MOD 786433
#define MAGIC (3*(1<<18))
const int root = 10;
void fft(vi &a, int wn = root)
{
int n = sz(a);
if (n == 3)
{
int a1 = a[0] + a[1] + a[2];
int a2 = (a[0] + a[1] * 1LL * root + a[2] * (root * 1LL * root)) % MOD;
a[1] = a1;
a[2] = a2;
return;
}
vi a0(n / 2), a1(n / 2);
for (int i = 0, j = 0; i<n; i += 2, ++j)
{
a0[j] = a[i];
a1[j] = a[i + 1];
}
int wnp = (wn * 1LL * wn) % MOD;
fft(a0, wnp);
fft(a1, wnp);
int w = 1;
for (int i = 0; i<n / 2; ++i) {
int twiddle = (w * 1LL * a1[i]) % MOD;
a[i] = (a0[i] + twiddle) % MOD;
a[i + n / 2] = (a0[i] - twiddle + MOD) % MOD;
w = (w * 1LL * wn) % MOD;
}
}
int n;
vi coef;
void poly(stringstream& ss)
{
ss >> n;
n++;
for (int i = 0; i<n; i++)
{
int x;
ss >> x;
coef.pb(x);
}
while (sz(coef)<MAGIC)
coef.pb(0);
vi ntt = coef;
fft(ntt);
vector<pint> sm;
sm.pb(mp(0, coef[0]));
int pr = 1;
for (int i = 0; i<sz(ntt); i++)
{
sm.pb(mp(pr, ntt[i]));
pr = (pr * 1LL * root) % MOD;
}
sort(all(sm));
int q;
ss >> q;
while (q--)
{
int x;
ss >> x;
int lo = 0, hi = sz(sm) - 1;
while (lo<hi)
{
int m = (lo + hi) / 2;
if (sm[m].fi<x)
lo = m + 1;
else
hi = m;
}
printf("%d\n", sm[lo].se);
}
}
void test1()
{
stringstream ss;
{
int degree = 2;
ss << degree << "\n";
string coefficients{ "1 2 3" };
ss << coefficients << "\n";
int NoQueries = 3;
ss << NoQueries << "\n";
int query = 7;
ss << query << "\n";
query = 8;
ss << query << "\n";
query = 9;
ss << query << "\n";
}
poly(ss);
}
int main()
{
test1();
return 0;
}
BTW.: This question is from the July 2016 challenge # code chef
Re
” Why do I need to use the modulo 786433 operator for all calculations? I understand that this might relate to int overflow? It this normal in competitive programming questions?
Yes, it's to avoid overflow.
And yes, it's normal in programming problem sets and competitions.

My perlin noise looks like wrong, almost like grey t-shirt material (heather). Why?

I tried a quick and dirty translation of the code here.
However, my version outputs noise comparable to grey t-shirt material, or heather if it please you:
#include <fstream>
#include "perlin.h"
double Perlin::cos_Interp(double a, double b, double x)
{
ft = x * 3.1415927;
f = (1 - cos(ft)) * .5;
return a * (1 - f) + b * f;
}
double Perlin::noise_2D(double x, double y)
{
/*
int n = (int)x + (int)y * 57;
n = (n << 13) ^ n;
int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 1.0 - ((double)nn / 1073741824.0);
*/
int n = (int)x + (int)y * 57;
n = (n<<13) ^ n;
return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
}
double Perlin::smooth_2D(double x, double y)
{
corners = ( noise_2D(x - 1, y - 1) + noise_2D(x + 1, y - 1) + noise_2D(x - 1, y + 1) + noise_2D(x + 1, y + 1) ) / 16;
sides = ( noise_2D(x - 1, y) + noise_2D(x + 1, y) + noise_2D(x, y - 1) + noise_2D(x, y + 1) ) / 8;
center = noise_2D(x, y) / 4;
return corners + sides + center;
}
double Perlin::interp(double x, double y)
{
int x_i = int(x);
double x_left = x - x_i;
int y_i = int(y);
double y_left = y - y_i;
double v1 = smooth_2D(x_i, y_i);
double v2 = smooth_2D(x_i + 1, y_i);
double v3 = smooth_2D(x_i, y_i + 1);
double v4 = smooth_2D(x_i + 1, y_i + 1);
double i1 = cos_Interp(v1, v2, x_left);
double i2 = cos_Interp(v3, v4, x_left);
return cos_Interp(i1, i2, y_left);
}
double Perlin::perlin_2D(double x, double y)
{
double total = 0;
double p = .25;
int n = 1;
for(int i = 0; i < n; ++i)
{
double freq = pow(2, i);
double amp = pow(p, i);
total = total + interp(x * freq, y * freq) * amp;
}
return total;
}
int main()
{
Perlin perl;
ofstream ofs("./noise2D.ppm", ios_base::binary);
ofs << "P6\n" << 512 << " " << 512 << "\n255\n";
for(int i = 0; i < 512; ++i)
{
for(int j = 0; j < 512; ++j)
{
double n = perl.perlin_2D(i, j);
n = floor((n + 1.0) / 2.0 * 255);
unsigned char c = n;
ofs << c << c << c;
}
}
ofs.close();
return 0;
}
I don't believe that I strayed too far from the aforementioned site's directions aside from adding in the ppm image generation code, but then again I'll admit to not fully grasping what is going on in the code.
As you'll see by the commented section, I tried two (similar) ways of generating pseudorandom numbers for noise. I also tried different ways of scaling the numbers returned by perlin_2D to RGB color values. These two ways of editing the code have just yielded different looking t-shirt material. So, I'm forced to believe that there's something bigger going on that I am unable to recognize.
Also, I'm compiling with g++ and the c++11 standard.
EDIT: Here's an example: http://imgur.com/Sh17QjK
To convert a double in the range of [-1.0, 1.0] to an integer in range [0, 255]:
n = floor((n + 1.0) / 2.0 * 255.99);
To write it as a binary value to the PPM file:
ofstream ofs("./noise2D.ppm", ios_base::binary);
...
unsigned char c = n;
ofs << c << c << c;
Is this a direct copy of your code? You assigned an integer to what should be the Y fractional value - it's a typo and it will throw the entire noise algorithm off if you don't fix:
double Perlin::interp(double x, double y)
{
int x_i = int(x);
double x_left = x - x_i;
int y_i = int(y);
double y_left = y = y_i; //This Should have a minus, not an "=" like the line above
.....
}
My guess is if you're successfully generating the bitmap with the proper color computation, you're getting vertical bars or something along those lines?
You also need to remember that the Perlin generator usually spits out numbers in the range of -1 to 1 and you need to multiply the resultant value as such:
value * 127 + 128 = {R, G, B}
to get a good grayscale image.