import java.util.HashSet ;
import java.util.Set ;
class Multimapa {
Set< Integer> [ ] pos;
int size;
int base;
private void initPos( int base) {
for ( int i = 0 ; i < base; i++ ) {
pos[ i] = new HashSet<> ( ) ;
}
}
public Multimapa( int n, int base) {
this .base = base;
initPos( base) ;
if ( n == 0 ) {
pos[ 0 ] .add ( 0 ) ;
size = 1 ;
return ;
}
if ( n < 0 ) {
n = - n;
}
int digitPos = 0 ;
while ( n > 0 ) {
int digit = n % base;
pos[ digit] .add ( digitPos) ;
n /= base;
digitPos++;
}
size = digitPos;
}
public static void main
( String [ ] args
) { // int qntNumerosInteressantes = 0;
// for (int i = 0; i < 99999999; i++) {
// if (julga(i, 10)) {
// System.out.println(i + " é capicua não repetido na base " + 10);
// qntNumerosInteressantes++;
// }
// }
// System.out.println("quantidade de números capicua e não repetidos nas base 10: " + qntNumerosInteressantes);
// qntNumerosInteressantes = 0;
// for (int i = 0; i < 99999999; i++) {
// if (julga(i, 16)) {
// System.out.println(i + " é capicua não repetido na base " + 16);
// qntNumerosInteressantes++;
// }
// }
// System.out.println("quantidade de números capicua e não repetidos nas base 16: " + qntNumerosInteressantes);
meta_julga( 0xffeff, 10 ) ; // 1048319
meta_julga( 121 , 10 ) ;
meta_julga( 1221 , 10 ) ;
meta_julga( 12721 , 10 ) ;
meta_julga( 12721 , 16 ) ; // 31b1
meta_julga( 0xffeff, 16 ) ;
meta_julga( 0xffdead, 16 ) ;
meta_julga( 0101, 8 ) ;
meta_julga( 0171, 8 ) ;
meta_julga( 01267621, 8 ) ;
meta_julga( 01267421, 8 ) ;
meta_julga( 5 , 2 ) ; // 101
meta_julga( 6 , 2 ) ; // 110
meta_julga( 7 , 2 ) ; // 111
meta_julga( 4 , 2 ) ; // 10
meta_julga( 16 , 3 ) ; // 121
meta_julga( 10 , 3 ) ; // 101
meta_julga( 12 , 3 ) ; // 110
}
private static void meta_julga( int n, int base) {
if ( julga( n, base) ) {
System .
out .
println ( n
+ " é capicua não repetido na base " + base
) ; } else {
System .
out .
println ( n
+ " não é capicua não repetido na base " + base
) ; }
}
// retorna verdade se todos os dígitos do número passado forem idênticos
//
// algoritmo de detecção: se, por acaso, existirem pelo menos dois dígitos com 1 ou mais posições, então é não repetido.
// caso seja tudo zero exceto por um único dígito, então é repetido
private static boolean ehNaoRepetido( Multimapa mm) {
int nDigitosDistintos = 0 ;
for ( int i = 0 ; i < mm.base ; i++ ) {
nDigitosDistintos += mm.pos [ i] .size ( ) > 0 ? 1 : 0 ;
}
return nDigitosDistintos > 1 ;
}
// retorna verdadeiro caso seja capicua
//
// algoritmo: verifica cada dígito; se for de tamanho `t` ímpar, então o dígito da posição `floor(t/2)` deve ser ignorado
// para um dígito `d` na posição `p` não ignorado, é necessário existir um outro dígito `d` na posição complementar `p'`, tal que `p + p' = t - 1`
private static boolean ehCapicua( Multimapa mm) {
int somaSimetrica = mm.size - 1 ;
int posIgnorada = mm.size % 2 == 1 ? mm.size / 2 : - 1 ;
for ( int d = 0 ; d < mm.base ; d++ ) {
// só tenta verificar se tem o complemento se e somente se não é ignorado
if ( p != posIgnorada) {
int posComplemento = somaSimetrica - p;
// se não existe o dígito na posição complementar, então não é capicua
if ( ! mm.pos [ d] .contains ( posComplemento) ) {
return false ;
}
}
}
}
return true ;
}
private static boolean julga( int n, int base) {
Multimapa mm = new Multimapa( n, base) ;
if ( ehNaoRepetido( mm) ) {
if ( ehCapicua( mm) ) {
return true ;
}
}
return false ;
}
}
aW1wb3J0IGphdmEudXRpbC5IYXNoU2V0OwppbXBvcnQgamF2YS51dGlsLlNldDsKCmNsYXNzIE11bHRpbWFwYSB7CgoJU2V0PEludGVnZXI+W10gcG9zOwoJaW50IHNpemU7CglpbnQgYmFzZTsKCQoJcHJpdmF0ZSB2b2lkIGluaXRQb3MoaW50IGJhc2UpIHsKCQlwb3MgPSBuZXcgSGFzaFNldFtiYXNlXTsKCQkKCQlmb3IgKGludCBpID0gMDsgaSA8IGJhc2U7IGkrKykgewoJCQlwb3NbaV0gPSBuZXcgSGFzaFNldDw+KCk7CgkJfQoJfQoJCglwdWJsaWMgTXVsdGltYXBhKGludCBuLCBpbnQgYmFzZSkgewoJCXRoaXMuYmFzZSA9IGJhc2U7CgkJaW5pdFBvcyhiYXNlKTsKCQkKCQlpZiAobiA9PSAwKSB7CgkJCXBvc1swXS5hZGQoMCk7CgkJCXNpemUgPSAxOwoJCQlyZXR1cm47CgkJfQoJCWlmIChuIDwgMCkgewoJCQluID0gLW47CgkJfQoJCWludCBkaWdpdFBvcyA9IDA7CgkJd2hpbGUgKG4gPiAwKSB7CgkJCWludCBkaWdpdCA9IG4gJSBiYXNlOwoJCQlwb3NbZGlnaXRdLmFkZChkaWdpdFBvcyk7CgkJCQoJCQluIC89IGJhc2U7CgkJCWRpZ2l0UG9zKys7CgkJfQoJCXNpemUgPSBkaWdpdFBvczsKCX0KCglwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CgkJLy8gaW50IHFudE51bWVyb3NJbnRlcmVzc2FudGVzID0gMDsKCQkvLyBmb3IgKGludCBpID0gMDsgaSA8IDk5OTk5OTk5OyBpKyspIHsKCQkvLyAJaWYgKGp1bGdhKGksIDEwKSkgewoJCS8vIAkJU3lzdGVtLm91dC5wcmludGxuKGkgKyAiIMOpIGNhcGljdWEgbsOjbyByZXBldGlkbyBuYSBiYXNlICIgKyAxMCk7CgkJLy8gCQlxbnROdW1lcm9zSW50ZXJlc3NhbnRlcysrOwoJCS8vIAl9CgkJLy8gfQoJCQoJCS8vIFN5c3RlbS5vdXQucHJpbnRsbigicXVhbnRpZGFkZSBkZSBuw7ptZXJvcyBjYXBpY3VhIGUgbsOjbyByZXBldGlkb3MgbmFzIGJhc2UgMTA6ICIgKyBxbnROdW1lcm9zSW50ZXJlc3NhbnRlcyk7CgkJCgkJLy8gcW50TnVtZXJvc0ludGVyZXNzYW50ZXMgPSAwOwoJCS8vIGZvciAoaW50IGkgPSAwOyBpIDwgOTk5OTk5OTk7IGkrKykgewoJCS8vIAlpZiAoanVsZ2EoaSwgMTYpKSB7CgkJLy8gCQlTeXN0ZW0ub3V0LnByaW50bG4oaSArICIgw6kgY2FwaWN1YSBuw6NvIHJlcGV0aWRvIG5hIGJhc2UgIiArIDE2KTsKCQkvLyAJCXFudE51bWVyb3NJbnRlcmVzc2FudGVzKys7CgkJLy8gCX0KCQkvLyB9CgkJCgkJLy8gU3lzdGVtLm91dC5wcmludGxuKCJxdWFudGlkYWRlIGRlIG7Dum1lcm9zIGNhcGljdWEgZSBuw6NvIHJlcGV0aWRvcyBuYXMgYmFzZSAxNjogIiArIHFudE51bWVyb3NJbnRlcmVzc2FudGVzKTsKCQkKCQltZXRhX2p1bGdhKDB4ZmZlZmYsIDEwKTsgLy8gMTA0ODMxOQoJCW1ldGFfanVsZ2EoMTIxLCAxMCk7CgkJbWV0YV9qdWxnYSgxMjIxLCAxMCk7CgkJbWV0YV9qdWxnYSgxMjcyMSwgMTApOwoJCW1ldGFfanVsZ2EoMTI3MjEsIDE2KTsgLy8gMzFiMQoJCW1ldGFfanVsZ2EoMHhmZmVmZiwgMTYpOwoJCW1ldGFfanVsZ2EoMHhmZmRlYWQsIDE2KTsKCQltZXRhX2p1bGdhKDAxMDEsIDgpOwoJCW1ldGFfanVsZ2EoMDE3MSwgOCk7CgkJbWV0YV9qdWxnYSgwMTI2NzYyMSwgOCk7CgkJbWV0YV9qdWxnYSgwMTI2NzQyMSwgOCk7CgoJCW1ldGFfanVsZ2EoNSwgMik7IC8vIDEwMQoJCW1ldGFfanVsZ2EoNiwgMik7IC8vIDExMAoJCW1ldGFfanVsZ2EoNywgMik7IC8vIDExMQoJCW1ldGFfanVsZ2EoNCwgMik7IC8vIDEwCgkJbWV0YV9qdWxnYSgxNiwgMyk7IC8vIDEyMQoJCW1ldGFfanVsZ2EoMTAsIDMpOyAvLyAxMDEKCQltZXRhX2p1bGdhKDEyLCAzKTsgLy8gMTEwCgl9CgkKCXByaXZhdGUgc3RhdGljIHZvaWQgbWV0YV9qdWxnYShpbnQgbiwgaW50IGJhc2UpIHsKCQlpZiAoanVsZ2EobiwgYmFzZSkpIHsKCQkJU3lzdGVtLm91dC5wcmludGxuKG4gKyAiIMOpIGNhcGljdWEgbsOjbyByZXBldGlkbyBuYSBiYXNlICIgKyBiYXNlKTsKCQl9IGVsc2UgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4obiArICIgbsOjbyDDqSBjYXBpY3VhIG7Do28gcmVwZXRpZG8gbmEgYmFzZSAiICsgYmFzZSk7CgkJfQoJfQoJCgkvLyByZXRvcm5hIHZlcmRhZGUgc2UgdG9kb3Mgb3MgZMOtZ2l0b3MgZG8gbsO6bWVybyBwYXNzYWRvIGZvcmVtIGlkw6pudGljb3MKCS8vCgkvLyBhbGdvcml0bW8gZGUgZGV0ZWPDp8Ojbzogc2UsIHBvciBhY2FzbywgZXhpc3RpcmVtIHBlbG8gbWVub3MgZG9pcyBkw61naXRvcyBjb20gMSBvdSBtYWlzIHBvc2nDp8O1ZXMsIGVudMOjbyDDqSBuw6NvIHJlcGV0aWRvLgoJLy8gY2FzbyBzZWphIHR1ZG8gemVybyBleGNldG8gcG9yIHVtIMO6bmljbyBkw61naXRvLCBlbnTDo28gw6kgcmVwZXRpZG8KCXByaXZhdGUgc3RhdGljIGJvb2xlYW4gZWhOYW9SZXBldGlkbyhNdWx0aW1hcGEgbW0pIHsKCQlpbnQgbkRpZ2l0b3NEaXN0aW50b3MgPSAwOwoJCQoJCWZvciAoaW50IGkgPSAwOyBpIDwgbW0uYmFzZTsgaSsrKSB7CgkJCW5EaWdpdG9zRGlzdGludG9zICs9IG1tLnBvc1tpXS5zaXplKCkgPiAwPyAxOiAwOwoJCX0KCQkKCQlyZXR1cm4gbkRpZ2l0b3NEaXN0aW50b3MgPiAxOwoJfQoJCgkvLyByZXRvcm5hIHZlcmRhZGVpcm8gY2FzbyBzZWphIGNhcGljdWEKCS8vCgkvLyBhbGdvcml0bW86IHZlcmlmaWNhIGNhZGEgZMOtZ2l0bzsgc2UgZm9yIGRlIHRhbWFuaG8gYHRgIMOtbXBhciwgZW50w6NvIG8gZMOtZ2l0byBkYSBwb3Npw6fDo28gYGZsb29yKHQvMilgIGRldmUgc2VyIGlnbm9yYWRvCgkvLyBwYXJhIHVtIGTDrWdpdG8gYGRgIG5hIHBvc2nDp8OjbyBgcGAgbsOjbyBpZ25vcmFkbywgw6kgbmVjZXNzw6FyaW8gZXhpc3RpciB1bSBvdXRybyBkw61naXRvIGBkYCBuYSBwb3Npw6fDo28gY29tcGxlbWVudGFyIGBwJ2AsIHRhbCBxdWUgYHAgKyBwJyA9IHQgLSAxYAoJcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBlaENhcGljdWEoTXVsdGltYXBhIG1tKSB7CgkJaW50IHNvbWFTaW1ldHJpY2EgPSBtbS5zaXplIC0gMTsKCQlpbnQgcG9zSWdub3JhZGEgPSBtbS5zaXplICUgMiA9PSAxPyBtbS5zaXplLzI6IC0xOwoJCQoJCWZvciAoaW50IGQgPSAwOyBkIDwgbW0uYmFzZTsgZCsrKSB7CgkJCWZvciAoSW50ZWdlciBwOiBtbS5wb3NbZF0pIHsKCQkJCS8vIHPDsyB0ZW50YSB2ZXJpZmljYXIgc2UgdGVtIG8gY29tcGxlbWVudG8gc2UgZSBzb21lbnRlIHNlIG7Do28gw6kgaWdub3JhZG8KCQkJCWlmIChwICE9IHBvc0lnbm9yYWRhKSB7CgkJCQkJaW50IHBvc0NvbXBsZW1lbnRvID0gc29tYVNpbWV0cmljYSAtIHA7CgkJCQkJCgkJCQkJLy8gc2UgbsOjbyBleGlzdGUgbyBkw61naXRvIG5hIHBvc2nDp8OjbyBjb21wbGVtZW50YXIsIGVudMOjbyBuw6NvIMOpIGNhcGljdWEKCQkJCQlpZiAoIW1tLnBvc1tkXS5jb250YWlucyhwb3NDb21wbGVtZW50bykpIHsKCQkJCQkJcmV0dXJuIGZhbHNlOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQlyZXR1cm4gdHJ1ZTsKCX0KCglwcml2YXRlIHN0YXRpYyBib29sZWFuIGp1bGdhKGludCBuLCBpbnQgYmFzZSkgewoJCU11bHRpbWFwYSBtbSA9IG5ldyBNdWx0aW1hcGEobiwgYmFzZSk7CgkJCgkJaWYgKGVoTmFvUmVwZXRpZG8obW0pKSB7CgkJCWlmIChlaENhcGljdWEobW0pKSB7CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX0KCQkKCQlyZXR1cm4gZmFsc2U7Cgl9Cn0K