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); }
__int64 mulmod(__int64 a, __int64 b, __int64 n) { __int64 r; if(!n) return -1; a %= n; b %= n; if (!b||!a) return 0; if (a<0) a += n; if (b<0) b += n; r = 0; while(b) { if(b&1) r = addmod(r,a,n); b>>=1; a = addmod(a,a,n); } return r; }
static int test_anr(UV a, UV n, UV r) { UV* pn; UV* res; UV i; int retval = 1; Newz(0, pn, r, UV); if (pn == 0) croak("Couldn't allocate space for polynomial of degree %lu\n", (unsigned long) r); a %= r; pn[0] = a; pn[1] = 1; res = poly_mod_pow(pn, n, r, n); res[n % r] = addmod(res[n % r], n - 1, n); res[0] = addmod(res[0], n - a, n); for (i = 0; i < r; i++) if (res[i] != 0) retval = 0; Safefree(res); Safefree(pn); return retval; }
/* k = 2 */ s = *x1; w = w3table[2]; tmp = MULMOD(*x2, w); s = addmod(s, tmp, umod); w = w3table[1]; tmp = MULMOD(*x3, w); s = addmod(s, tmp, umod); *x3 = s; *x2 = r2; *x1 = r1; } #else /* PPRO */ static inline void ppro_size3_ntt(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_uint_t w3table[3], mpd_uint_t umod, double *dmod, uint32_t dinvmod[3]) { mpd_uint_t r1, r2; mpd_uint_t w; mpd_uint_t s, tmp; /* k = 0 -> w = 1 */ s = *x1; s = addmod(s, *x2, umod); s = addmod(s, *x3, umod); r1 = s; /* k = 1 */ s = *x1; w = w3table[1]; tmp = ppro_mulmod(*x2, w, dmod, dinvmod); s = addmod(s, tmp, umod); w = w3table[2]; tmp = ppro_mulmod(*x3, w, dmod, dinvmod); s = addmod(s, tmp, umod); r2 = s; /* k = 2 */ s = *x1; w = w3table[2]; tmp = ppro_mulmod(*x2, w, dmod, dinvmod); s = addmod(s, tmp, umod); w = w3table[1]; tmp = ppro_mulmod(*x3, w, dmod, dinvmod); s = addmod(s, tmp, umod); *x3 = s; *x2 = r2; *x1 = r1; }
static inline void std_size3_ntt(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_uint_t w3table[3], mpd_uint_t umod) { mpd_uint_t r1, r2; mpd_uint_t w; mpd_uint_t s, tmp; /* k = 0 -> w = 1 */ s = *x1; s = addmod(s, *x2, umod); s = addmod(s, *x3, umod); r1 = s; /* k = 1 */ s = *x1; w = w3table[1]; tmp = MULMOD(*x2, w); s = addmod(s, tmp, umod); w = w3table[2]; tmp = MULMOD(*x3, w); s = addmod(s, tmp, umod); r2 = s; /* k = 2 */ s = *x1; w = w3table[2]; tmp = MULMOD(*x2, w); s = addmod(s, tmp, umod); w = w3table[1]; tmp = MULMOD(*x3, w); s = addmod(s, tmp, umod); *x3 = s; *x2 = r2; *x1 = r1; }
/* Fast Number Theoretic Transform, decimation in frequency. */ void fnt_dif2(mpd_uint_t a[], mpd_size_t n, struct fnt_params *tparams) { mpd_uint_t *wtable = tparams->wtable; mpd_uint_t umod; #ifdef PPRO double dmod; uint32_t dinvmod[3]; #endif mpd_uint_t u0, u1, v0, v1; mpd_uint_t w, w0, w1, wstep; mpd_size_t m, mhalf; mpd_size_t j, r; assert(ispower2(n)); assert(n >= 4); SETMODULUS(tparams->modnum); /* m == n */ mhalf = n / 2; for (j = 0; j < mhalf; j += 2) { w0 = wtable[j]; w1 = wtable[j+1]; u0 = a[j]; v0 = a[j+mhalf]; u1 = a[j+1]; v1 = a[j+1+mhalf]; a[j] = addmod(u0, v0, umod); v0 = submod(u0, v0, umod); a[j+1] = addmod(u1, v1, umod); v1 = submod(u1, v1, umod); MULMOD2(&v0, w0, &v1, w1); a[j+mhalf] = v0; a[j+1+mhalf] = v1; } wstep = 2; for (m = n/2; m >= 2; m>>=1, wstep<<=1) { mhalf = m / 2; /* j == 0 */ for (r = 0; r < n; r += 2*m) { u0 = a[r]; v0 = a[r+mhalf]; u1 = a[m+r]; v1 = a[m+r+mhalf]; a[r] = addmod(u0, v0, umod); v0 = submod(u0, v0, umod); a[m+r] = addmod(u1, v1, umod); v1 = submod(u1, v1, umod); a[r+mhalf] = v0; a[m+r+mhalf] = v1; } for (j = 1; j < mhalf; j++) { w = wtable[j*wstep]; for (r = 0; r < n; r += 2*m) { u0 = a[r+j]; v0 = a[r+j+mhalf]; u1 = a[m+r+j]; v1 = a[m+r+j+mhalf]; a[r+j] = addmod(u0, v0, umod); v0 = submod(u0, v0, umod); a[m+r+j] = addmod(u1, v1, umod); v1 = submod(u1, v1, umod); MULMOD2C(&v0, &v1, w); a[r+j+mhalf] = v0; a[m+r+j+mhalf] = v1; } } } bitreverse_permute(a, n); }
static void poly_mod_sqr(UV* px, UV* res, UV r, UV mod) { UV c, d, s, sum, rindex, maxpx; UV degree = r-1; int native_sqr = (mod > isqrt(UV_MAX/(2*r))) ? 0 : 1; memset(res, 0, r * sizeof(UV)); /* zero out sums */ /* Discover index of last non-zero value in px */ for (s = degree; s > 0; s--) if (px[s] != 0) break; maxpx = s; /* 1D convolution */ for (d = 0; d <= 2*degree; d++) { UV *pp1, *pp2, *ppend; UV s_beg = (d <= degree) ? 0 : d-degree; UV s_end = ((d/2) <= maxpx) ? d/2 : maxpx; if (s_end < s_beg) continue; sum = 0; pp1 = px + s_beg; pp2 = px + d - s_beg; ppend = px + s_end; if (native_sqr) { while (pp1 < ppend) sum += 2 * *pp1++ * *pp2--; /* Special treatment for last point */ c = px[s_end]; sum += (s_end*2 == d) ? c*c : 2*c*px[d-s_end]; rindex = (d < r) ? d : d-r; /* d % r */ res[rindex] = (res[rindex] + sum) % mod; #if defined(HAVE_UINT128) } else { uint128_t max = ((uint128_t)1 << 127) - 1; uint128_t c128, sum128 = 0; while (pp1 < ppend) { c128 = ((uint128_t)*pp1++) * ((uint128_t)*pp2--); if (c128 > max) c128 %= mod; c128 <<= 1; if (c128 > max) c128 %= mod; sum128 += c128; if (sum128 > max) sum128 %= mod; } c128 = px[s_end]; if (s_end*2 == d) { c128 *= c128; } else { c128 *= px[d-s_end]; if (c128 > max) c128 %= mod; c128 <<= 1; } if (c128 > max) c128 %= mod; sum128 += c128; if (sum128 > max) sum128 %= mod; rindex = (d < r) ? d : d-r; /* d % r */ res[rindex] = ((uint128_t)res[rindex] + sum128) % mod; #else } else { while (pp1 < ppend) { UV p1 = *pp1++; UV p2 = *pp2--; sum = addmod(sum, mulmod(2, mulmod(p1, p2, mod), mod), mod); } c = px[s_end]; if (s_end*2 == d) sum = addmod(sum, sqrmod(c, mod), mod); else sum = addmod(sum, mulmod(2, mulmod(c, px[d-s_end], mod), mod), mod); rindex = (d < r) ? d : d-r; /* d % r */ res[rindex] = addmod(res[rindex], sum, mod); #endif } }