|
НОИ - 2 кръг, 2006 г., задача Ident
Уловието на задачата може да прочетете
тук.
Решение
Идеята на решението на тази задача е да се пробват да се построят
числа, които се делят на A с всички възможни цифри. За да се намери най-малкото
число с еднакви цифри, което се дели на A се започва с число, което съдържа една
такава цифра. Нека цифрата е x. Последователно се изпробват числа
състоящи се само от тази цифра и с все по-голяма дължина. За да се пресметне
остатъка при делене на A за дадено число може да се използва остатъка за числото с една
цифра ‘x’ по-малко. Ако този остатък е
r, то новия остатък е (r*P+x)%A, като
P е
основата на бройната система. По този начин постепенно се изпробват числа с все
повече цифри докато или се получи такова, което се дели на A или се получи остатък, който
вече е бил срещан. Ако един остатък се повтори това означава, че остатъците,
които ще се получават нататък ще се повтарят и никога няма да се получи остатък
0. В този случай няма смисъл да се
продължава. Различният брой остатъци при делене на A е А. От тук следва, че максималният брой цифри, до който може да се
достигне е A. От всички числа, които се получават се избира това, което има
най-малко цифри, защото то е най-малкото като стойност. Сложността на това
решение е O(A*P), тъй като се изпробват всички видове цифри
и за всяка цифра се изпробват числа с максимум A на брой цифри.
Примерна реализация
#include <stdio.h>
#define MAXA 1000004
#define MAXP 104
#define INF 10000000
int a,p;
// list with the remainders that we already met
int rem[MAXA];
// the length of the shortest number
int minlen;
// the digit used in the smallest number
int mindig;
int main()
{
int i;
int curn;
int brdig;
scanf("%d %d",&a,&p);
minlen = INF;
mindig = 0;
// try all the possible digits
for(i=1;i<p;i++)
{
// start with a one-digit number
curn = i;
brdig = 1;
while(curn%a != 0)
{
// check if this remainder was already met
if(rem[curn%a]==i)
break;
else
rem[curn%a] = i;
// add one more digit and compute the new remainder
curn = (curn*p+i)%a;
brdig++;
}
// check if this number is smaller
// than the smallest until now
if(curn%a==0 && brdig<minlen)
{
minlen = brdig;
mindig = i;
}
}
// print the answer if such was found
// otherwise print 0
if(mindig!=0)
printf("%d %d\n",minlen,mindig);
else
printf("0\n");
return 0;
}
Автор: Антон Димитров
обратно към текущ брой
|