A bit of help with problem ZDI did not anticipate it at first, but it turns out that problem ZD has a nasty overflow problem. If you try to use the powmod() function from the provided number.cpp, it will fail because the line "r *= r;" will try to square a number that is slightly larger than 232. There is a rather ugly fix to this. Try using this powmod() function instead of the one from the collection of number theoretic algorithms. typedef unsigned long long ull; /** * Multiplies two numbers and returns the product modulo n * ull is unsigned long long **/ ull multmod( ull a, ull b, ull n ) { ull a0 = a & 0xFFFFFFFFLL; ull a1 = a >> 32; ull b0 = b & 0xFFFFFFFFLL; ull b1 = b >> 32; /** * The point of the 4 lines above is to make * a = a0 + ( a1 << 32 ); * b = b0 + ( b1 << 32 ); * Now expand * a * b = ( a0 + ( a1 << 32 ) ) * * ( b0 + ( b1 << 32 ) ) * into 4 terms and evaluate each one modulo n. * The assumption here is that a, b and n are only * slightly bigger than ( 1 << 32 ). **/ // The a0 * b0 term ull ans = ( a0 * b0 ) % n; // The a0 * b1 * 2^32 term [ = ( a0 * ( 2^32 - 1 ) + a0 ) * b1 ] ans += ( ( ( ( a0 * 0xFFFFFFFFLL ) % n ) + a0 ) * b1 ) % n; // The a1 * 2^32 * b0 term [ = ( b0 * ( 2^32 - 1 ) + b0 ) * a1 ] ans += ( ( ( ( b0 * 0xFFFFFFFFLL ) % n ) + b0 ) * a1 ) % n; // The a1 * b1 * 2^64 term [ = ( ( 2^64 - 1 ) + 1 ) * a1 * b1 ] ans += ( ( ( ( ( ( ull )0xFFFFFFFFFFFFFFFFLL % n ) + 1 ) * a1 ) % n ) * b1 ) % n; return ans % n; } ull powmod( ull b, ull p, ull m ) { ull r = 1; for( ull i = ( ( ull )1 << 63 ); i; i >>= 1 ) { r = multmod( r, r, m ); if( p & i ) r = multmod( r, b, m ); } return r; } |