LL powmod(LL a, LL b, LL p){ LL res = 1; while(b){ if(b & 1) res = multmod(res, a, p); a = multmod(a, a, p), b >>= 1; } return res; }
int main() { vector<i64> vn2; i64 nmax = 123456787654321; vn2.push_back(nmax % nmod); i64 n = nmax; int count = 0; while(n){ n/=2; vn2.push_back(n % nmod); vn2[count] -= vn2[count+1]; ++count; } i64 sum = 0; for(int i = 0; i<(int)vn2.size(); ++i){ for(int j = i; j<(int)vn2.size();++j){ for(int k=j; k<(int)vn2.size();++k){ i64 mult = 6; if(i==j && j==k) mult = 1; else if(i==j||j==k||i==k){ mult = 3; } if((i^j^k)==0){ mult = multmod(mult, vn2[i], nmod); mult = multmod(mult, vn2[j], nmod); mult = multmod(mult, vn2[k], nmod); printf("%d %d %d %lld %lld %lld %lld\n", i, j, k, vn2[i], vn2[j], vn2[k], mult); sum = addmod(sum ,mult, nmod); } } } } i64 nx = nmax%nmod; i64 x0 = multmod(nx, nx, nmod); x0 = multmod(x0, nx, nmod); sum = addmod(x0, -sum, nmod); if(sum < 0) sum += nmod; printf("%lld\n", sum); }
void advance_state(int k) /******************************************************************************/ /* Purpose: ADVANCE_STATE advances the state of the current generator. Discussion: This procedure advances the state of the current generator by 2^K values and resets the initial seed to that value. Licensing: This code is distributed under the GNU LGPL license. Modified: 30 March 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Input, int K, indicates that the generator is to be advanced by 2^K values. 0 <= K. */ { const int a1 = 40014; const int a2 = 40692; int b1; int b2; int cg1; int cg2; int g; int i; const int m1 = 2147483563; const int m2 = 2147483399; if (k < 0) { fprintf(stderr, "\n"); fprintf(stderr, "ADVANCE_STATE - Fatal error!\n"); fprintf(stderr, " Input exponent K is out of bounds.\n"); exit(1); } /* Check whether the package must be initialized. */ if (!initialized_get()) { initialize(); } /* Get the current generator index. */ g = cgn_get(); b1 = a1; b2 = a2; for (i = 1; i <= k; k++) { b1 = multmod(b1, b1, m1); b2 = multmod(b2, b2, m2); } cg_get(g, &cg1, &cg2); cg1 = multmod(b1, cg1, m1); cg2 = multmod(b2, cg2, m2); cg_set(g, cg1, cg2); return; }
void init_generator(int t) /******************************************************************************/ /* Purpose: INIT_GENERATOR sets the state of generator G to initial, last or new seed. Licensing: This code is distributed under the GNU LGPL license. Modified: 01 April 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Input, int T, the seed type: 0, use the seed chosen at initialization time. 1, use the last seed. 2, use a new seed set 2^30 values away. */ { const int a1_w = 1033780774; const int a2_w = 1494757890; int cg1; int cg2; int g; int ig1; int ig2; int lg1; int lg2; const int m1 = 2147483563; const int m2 = 2147483399; /* Check whether the package must be initialized. */ if (!initialized_get()) { initialize(); } /* Get the current generator index. */ g = cgn_get(); /* 0: restore the initial seed. */ if (t == 0) { ig_get(g, &ig1, &ig2); lg1 = ig1; lg2 = ig2; lg_set(g, lg1, lg2); } /* 1: restore the last seed. */ else if (t == 1) { lg_get(g, &lg1, &lg2); } /* 2: advance to a new seed. */ else if (t == 2) { lg_get(g, &lg1, &lg2); lg1 = multmod(a1_w, lg1, m1); lg2 = multmod(a2_w, lg2, m2); lg_set(g, lg1, lg2); } else { fprintf(stderr, "\n"); fprintf(stderr, "INIT_GENERATOR - Fatal error!\n"); fprintf(stderr, " Input parameter T out of bounds.\n"); exit(1); } /* Store the new seed. */ cg1 = lg1; cg2 = lg2; cg_set(g, cg1, cg2); return; }
void set_initial_seed(int ig1, int ig2) /******************************************************************************/ /* Purpose: SET_INITIAL_SEED resets the initial seed and state for all generators. Licensing: This code is distributed under the GNU LGPL license. Modified: 28 March 2013 Author: Original Pascal version by Pierre L'Ecuyer, Serge Cote. C version by John Burkardt. Reference: Pierre LEcuyer, Serge Cote, Implementing a Random Number Package with Splitting Facilities, ACM Transactions on Mathematical Software, Volume 17, Number 1, March 1991, pages 98-111. Parameters: Input, int IG1, IG2, the initial seed values for the first generator. 1 <= IG1 < 2147483563 1 <= IG2 < 2147483399 */ { const int a1_vw = 2082007225; const int a2_vw = 784306273; int g; const int g_max = 32; //int i; const int m1 = 2147483563; const int m2 = 2147483399; int t; if (ig1 < 1 || m1 <= ig1) { fprintf(stderr, "\n"); fprintf(stderr, "SET_INITIAL_SEED - Fatal error!\n"); fprintf(stderr, " Input parameter IG1 out of bounds.\n"); exit(1); } if (ig2 < 1 || m2 <= ig2) { fprintf(stderr, "\n"); fprintf(stderr, "SET_INITIAL_SEED - Fatal error!\n"); fprintf(stderr, " Input parameter IG2 out of bounds.\n"); exit(1); } /* Because INITIALIZE calls SET_INITIAL_SEED, it's not easy to correct the error that arises if SET_INITIAL_SEED is called before INITIALIZE. So don't bother trying. */ if (!initialized_get()) { printf("\n"); printf("SET_INITIAL_SEED - Fatal error!\n"); printf(" The RNGLIB package has not been initialized.\n"); exit(1); } /* Set the initial seed, then initialize the first generator. */ g = 0; cgn_set(g); ig_set(g, ig1, ig2); t = 0; init_generator(t); /* Now do similar operations for the other generators. */ for (g = 1; g < g_max; g++) { cgn_set(g); ig1 = multmod(a1_vw, ig1, m1); ig2 = multmod(a2_vw, ig2, m2); ig_set(g, ig1, ig2); init_generator(t); } /* Now choose the first generator. */ g = 0; cgn_set(g); return; }