#include #include #include #include #include //#ifdef UNIX typedef long long LLONG; //#define FMT1 "%llu\n" //#define FMT2 "%llu/%llu\n" //#define FMT3 "%llu %llu/%llu\n" //#else //typedef __int64 LLONG; //#define FMT1 "%I64u\n" //#define FMT2 "%I64u/%I64u\n" //#define FMT3 "%I64u %I64u/%I64u\n" //#endif typedef unsigned long DWORD; #define MAX_PROFS 20 char baseString[MAX_PROFS + 1] = "ABCDEFGHIJKLMNOPQRST"; char instr[MAX_PROFS + 1]; int nprofs, nxtPrimeFact, usedPrimes; LLONG primePows[MAX_PROFS + 1]; LLONG primePowRems[MAX_PROFS + 1]; LLONG primePowFact[MAX_PROFS + 1]; LLONG primePowProd, source; char work[MAX_PROFS + 1]; int rems[MAX_PROFS + 1]; void shift(char *p, int n) { int i; char *pp = p+1; for(i = 0; i < n ; i++) *p++ = *pp++; } typedef struct _fact_data_ { int leastDiv; int divRem; int primeFact; } FACT_DATA, *PFACT_DATA; FACT_DATA factData[MAX_PROFS + 1] = { {0, 0, 0}, {0, 0, 0}, {2, 1, 1}, {3, 1, 2}, {2, 2, 1}, {5, 1, 3}, {2, 3, 0}, {7, 1, 4}, {2, 4, 1}, {3, 3, 2}, {2, 5, 0}, {11, 1, 5}, {2, 6, 0}, {13, 1, 6}, {2, 7, 0}, {3, 5, 0}, {2, 8, 1}, {17, 1, 7}, {2, 9, 0}, {19, 1, 8}, {2, 10, 0}, }; void decode() { int i, n, j; char cur; for(i = 0; i < nprofs ; i++) { work[i] = baseString[i]; } for(i = 0, n = nprofs; i < nprofs ; i++, n--) { cur = instr[i]; j = ((cur -'A')*n)/nprofs; while(work[j] != cur) { if(work[j] > cur) j--; else j++; } rems[n] = j; shift(&work[j], n-j); } } int checkRems() { int i; usedPrimes = 0; for(i = 2; i <= nprofs ; i++) { if(factData[i].divRem == 1) { primePows[factData[i].primeFact] = i; primePowRems[factData[i].primeFact] = rems[i]; usedPrimes++; } else { if((rems[i] % factData[i].divRem) != rems[factData[i].divRem]) { return -1; } if((rems[i] % factData[i].leastDiv) != rems[factData[i].leastDiv]) { return -1; } if(factData[i].primeFact != 0) { primePows[factData[i].primeFact] = i; primePowRems[factData[i].primeFact] = rems[i]; } } } return 0; } // assum n1 > n2 return q = GCD(n1, n2) and d1 and d2 so d1*n1 + d2*n2 = q (which will bw one in use LLONG ExtEuclid(LLONG n1, LLONG n2, LLONG *pd1, LLONG *pd2) { LLONG q, c1, c2; if(n2 == 0) { *pd1 = 1; *pd2 = 0; return n1; } q = ExtEuclid(n2, (n1 % n2), &c1, &c2); *pd1 = c2; *pd2 = c1 - (n1/n2)*c2; return q; } int Validate() { int i; for(i = 2; i <= nprofs ; i++) { if((source%i) != rems[i]) { fprintf(stderr, "mismatched rem at %d source %lld rem %d\n", i, source, rems[i]); return -42; } } return 0; } int FindSource() { int i; LLONG c1, c2, q; source = 0; for(i = 1, primePowProd = 1 ; i <= usedPrimes ; i++) { primePowProd *= primePows[i]; } for(i = 1 ; i <= usedPrimes ; i++) { primePowFact[i] = primePowProd/primePows[i]; q = ExtEuclid(primePowFact[i], primePows[i], &c1, &c2); if(q != 1) return -31; source += primePowFact[i]*c1*primePowRems[i]; } while(source < 0) { source += primePowProd; } if(source > primePowProd) { source = source % primePowProd; } return 0; } /* NOT USED void MakeFactData() { int i, j, k; nxtPrimeFact = 1; ::memset(&factData[0], 0, MAX_PROFS + 1*sizeof(FACT_DATA)); for(i = 2; i <= MAX_PROFS ; i++) { if(factData[i].leastDiv == 0) { factData[i].leastDiv = i; factData[i].divRem = 1; factData[i].primeFact = nxtPrimeFact++; for(k = 2, j = 2*i; j <= MAX_PROFS ; j += i, k++) { if(factData[j].leastDiv == 0) { factData[j].leastDiv = i; factData[j].divRem = k; if(factData[k].primeFact == factData[i].primeFact) factData[j].primeFact = factData[i].primeFact; } } } } for(i = 0; i <= MAX_PROFS ; i++) { printf("\t{%d, %d, %d},\n", factData[i].leastDiv, factData[i].divRem, factData[i].primeFact); } } */ int ParseInput(int n, char last) { char c; int i, chcnt; chcnt = 0; for(i = 0; i < n ; i++) { if((c = getc(stdin)) == EOF) { return -21; } if((c < 'A') || (c > last)) { return -22; } instr[chcnt] = c; chcnt++; } return 0; } char inbuf[256]; int main() { int ret; if(fgets(&(inbuf[0]), 255, stdin) == NULL) { fprintf(stderr, "read failed on prof count\n"); return -1; } if(sscanf(&(inbuf[0]), "%d", &nprofs) != 1) { fprintf(stderr, "scan failed on prof count\n"); return -2; } if((nprofs < 5) || (nprofs > MAX_PROFS)) { fprintf(stderr, "num rprofs (%d) not in range 5 ... %d\n", nprofs, MAX_PROFS); return -3; } if((ret = ParseInput(nprofs, baseString[nprofs-1])) != 0) { return ret; } decode(); ret = checkRems(); if(ret != 0) { printf("NO\n"); } else { printf("YES\n"); if((ret = FindSource()) != 0) return ret; printf("%ld\n", (long)source); } return 0; }