Mam nadzieję, że nie będzie miał mi tego za złe, w końcu już wygrał, a inni mogą się z tego wiele nauczyć.
#include <stdio.h>
#include <stdlib.h>
/*int invMod(unsigned a, unsigned b) {
const unsigned m = a;
register unsigned c, quot;
register int p=1, q=0, r=0, s=1;
while(b) {
quot = a/b;
c = p - quot*r;
p = r;
r = c;
c = q - quot*s;
q = s;
s = c;
c = a % b;
a = b;
b = c;
}
return (q+m) % m;
//return q>0?q:(q+m);
}*/
struct data {
unsigned n, k;
unsigned d2, d5;
unsigned res1, res2;
};
struct datacontainer {
unsigned k;
data *d;
};
int dccmp(const void *a, const void *b) {
return (long)((datacontainer*)a)->k - (long)((datacontainer*)b)->k;
}
int main(void) {
unsigned n, k, l;
unsigned num;
unsigned invMod16[] = {1, 11, 13, 7, 9, 3, 5, 15};
unsigned invMod625[] = {1,
1, 313, 417, 469, 0, 521, 268, 547, 139, 0, 341, 573, 577, 134, 0, 586, 478, 382, 329, 0,
506, 483, 462, 599, 0, 601, 463, 67, 194, 0, 121, 293, 322, 239, 0, 191, 473, 477, 609, 0,
61, 253, 407, 554, 0, 231, 133, 612, 574, 0, 576, 613, 342, 544, 0, 346, 318, 97, 339, 0,
41, 373, 377, 459, 0, 161, 28, 432, 154, 0, 581, 408, 137, 549, 0, 551, 138, 617, 269, 0,
571, 343, 497, 439, 0, 516, 273, 277, 309, 0, 261, 428, 457, 379, 0, 306, 58, 287, 524, 0,
526, 288, 267, 619, 0, 171, 368, 272, 539, 0, 366, 173, 177, 159, 0, 361, 203, 482, 604, 0,
31, 333, 437, 499, 0, 501, 438, 542, 344, 0, 396, 393, 47, 14, 0, 216, 73, 77, 9, 0,
461, 603, 507, 204, 0, 381, 608, 587, 474, 0, 476, 588, 192, 69, 0, 621, 418, 447, 114, 0,
66, 598, 602, 484, 0, 561, 378, 532, 429, 0, 106, 258, 112, 449, 0, 451, 113, 467, 419, 0,
221, 443, 222, 214, 0, 541, 498, 502, 334, 0, 36, 153, 557, 29, 0, 456, 533, 262, 424, 0,
426, 263, 117, 144, 0, 446, 468, 622, 314, 0, 391, 398, 402, 184, 0, 136, 553, 582, 254, 0,
181, 183, 412, 399, 0, 401, 413, 392, 494, 0, 46, 493, 397, 414, 0, 241, 298, 302, 34, 0,
236, 328, 607, 479, 0, 531, 458, 562, 374, 0, 376, 563, 42, 219, 0, 271, 518, 172, 514, 0,
91, 198, 202, 509, 0, 336, 103, 7, 79, 0, 256, 108, 87, 349, 0, 351, 88, 317, 569, 0,
496, 543, 572, 614, 0, 566, 98, 102, 359, 0, 436, 503, 32, 304, 0, 606, 383, 237, 324, 0,
326, 238, 592, 294, 0, 96, 568, 347, 89, 0, 416, 623, 2, 209, 0, 536, 278, 57, 529, 0,
331, 33, 387, 299, 0, 301, 388, 242, 19, 0, 321, 593, 122, 189, 0, 266, 523, 527, 59, 0,
11, 53, 82, 129, 0, 56, 308, 537, 274, 0, 276, 538, 517, 369, 0, 546, 618, 522, 289, 0,
116, 423, 427, 534, 0, 111, 453, 107, 354, 0, 406, 583, 62, 249, 0, 251, 63, 167, 94, 0,
146, 18, 297, 389, 0, 591, 323, 327, 384, 0, 211, 228, 132, 579, 0, 131, 233, 212, 224, 0,
226, 213, 442, 444, 0, 371, 43, 72, 489, 0, 441, 223, 227, 234, 0, 311, 3, 157, 179, 0,
481, 508, 362, 199, 0, 201, 363, 92, 169, 0, 596, 68, 472, 589, 0, 291, 123, 127, 84, 0,
411, 403, 182, 404, 0, 206, 158, 512, 174, 0, 176, 513, 367, 519, 0, 196, 93, 247, 64, 0,
141, 23, 27, 559, 0, 511, 178, 207, 4, 0, 556, 433, 37, 149, 0, 151, 38, 17, 244, 0,
421, 118, 22, 164, 0, 616, 548, 552, 409, 0, 611, 578, 232, 229, 0, 281, 83, 187, 124, 0,
126, 188, 292, 594, 0, 21, 143, 422, 264, 0, 466, 448, 452, 259, 0, 86, 353, 257, 454, 0,
6, 358, 337, 99, 0, 101, 338, 567, 319, 0, 246, 168, 197, 364, 0, 316, 348, 352, 109, 0,
186, 128, 282, 54, 0, 356, 8, 487, 74, 0, 76, 488, 217, 44, 0, 471, 193, 597, 464, 0,
166, 248, 252, 584, 0, 286, 528, 307, 279, 0, 81, 283, 12, 49, 0, 51, 13, 492, 394, 0,
71, 218, 372, 564, 0, 16, 148, 152, 434, 0, 386, 303, 332, 504, 0, 431, 558, 162, 24, 0,
26, 163, 142, 119, 0, 296, 243, 147, 39, 0, 491, 48, 52, 284, 0, 486, 78, 357, 104, 0,
156, 208, 312, 624};
// tablica z odwrotnosciami modulo 625, zeby generowac dynamicznie odkomentuj kod ponizej i funkcje invMod
register unsigned i, j;
register unsigned d2, d5;
register unsigned result1, result2;
unsigned maxk;
/*int invMod625[625];
for (i=1; i<625; ++i) {
if (i % 5) {
invMod625[i] = invMod(625, i);
//printf("% 4d, ", invMod625[i]);
//} else {
//printf(" 0, ");
}
//if (i % 20 == 0) printf("\n");
}*/
scanf("%d", &num);
data *d = (data*)malloc(sizeof(data)*num);
datacontainer *dc = (datacontainer*)malloc(sizeof(datacontainer)*num);
if (!d || !dc) {
fprintf(stderr, "Nie mozna zaalokowac pamieci\n");
exit(0);
}
maxk = 0;
for (l=0; l<num; ++l) {
scanf("%d%d", &n, &k);
if (k*2 > n) k = n-k;
if (k > maxk) maxk = k;
d[l] = (data){n, k};
dc[l] = (datacontainer){k, d+l};
}
qsort(dc, num, sizeof(datacontainer), dccmp);
d2 = d5 = 0;
result1 = result2 = 1;
l = 0;
while(dc[l].k == 0) {
dc[l].d->d2 = 0;
dc[l].d->d5 = 0;
dc[l].d->res1 = 1;
dc[l].d->res2 = 1;
++l;
}
for (i=1; i<=maxk; ++i) {
for(j=i; ~j&1; j=j>>1, ++d2);
result1 = (result1 * invMod16[(j&15)>>1]) &15;
for(j=i; j%5==0; j/=5, ++d5);
result2 = (result2 * invMod625[j%625]) % 625;
while (dc[l].k == i) {
dc[l].d->d2 = d2;
dc[l].d->d5 = d5;
dc[l].d->res1 = result1;
dc[l].d->res2 = result2;
++l;
}
}
for(l=0; l<num; ++l) {
n = d[l].n;
k = d[l].k;
d2 = d[l].d2;
d5 = d[l].d5;
result1 = d[l].res1;
result2 = d[l].res2;
for (i=0; i<k; ++i) {
for(j=n-i; d2 && ~j&1; j=j>>1, --d2);
result1 = (result1 * (j&15)) &15;
for(j=n-i; d5 && j%5==0; j/=5, --d5);
result2 = (result2 * (j % 625)) % 625;
}
d2 = ((result2 - result1) % 625) * 586;
result2 = (result1 + (d2<<4)) % 10000;
printf("%d\n", result2);
}
return 0;
}