Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ITSF ` ²V2b ý|ª{О É"æìý|ª{О É"æì` x T` Ì` þ a( ITSP T
- ÿÿÿÿ j’].!Ðù É"æìT ÿÿÿÿࠃࠃࠃࠃࠃࠃࠐMGL^ ÿÿÿÿ / /#IDXHDR„„q /#ITBITS /#STRINGS†²Ô/#SYSTEM …N¡5/#TOPICS„¤qË /#URLSTR…¨M‰G/#URLTBL„ð¸< /#WINDOWSö¿kL/$FIftiMainøÅY‹¿ /$OBJINSTø°•?/$WWAssociativeLinks/ /$WWAssociativeLinks/Propertyø°/$WWKeywordLinks/ /$WWKeywordLinks/BTreeöÁ7ÀL/$WWKeywordLinks/Dataø‚/$WWKeywordLinks/Mapø¯Z/$WWKeywordLinks/Propertyø¯v
- /ascii.htmŠÉF˜-/c/
- /c/all.htm‹ás±/c/date/ /c/date/asctime.htm’x
- /c/date/clock.htm£‹ /c/date/ctime.htm®ŽR/c/date/datime.htm¼`‰m/c/date/difftime.htmÆMŠ)/c/date/gmtime.htmÐv`/c/date/localtime.htmÞV” /c/date/mktime.htmòVŒH/c/date/setlocale.htmÿ’2/c/date/start.htmŽ‘P”:/c/date/strftime.htmަ
- £V/c/date/time.htmŽÉ`Žj/c/io/ /c/io/clearerr.htmŽØJŠm/c/io/fclose.htmŽã7‹/c/io/feof.htmŽîSŠl/c/io/ferror.htmŽù?ŠY/c/io/fflush.htm„—/c/io/fgetc.htm›)Œv/c/io/fgetpos.htm¨Œ/c/io/fgets.htm´ Ž
- /c/io/fopen.htmÂ-Ÿ/c/io/fprintf.htmá5“Z/c/io/fpurge.htmõ•/c/io/fputc.htmŠ"X/c/io/fputs.htm—zŒ0/c/io/fread.htm¤*4/c/io/freopen.htm´^/c/io/fscanf.htmÁoŽ/c/io/fseek.htmÏ~’P/c/io/fsetpos.htmâN‹C/c/io/ftell.htmî‰j/c/io/fwrite.htm÷{"/c/io/getc.htm‘…”t/c/io/getchar.htm‘šŠR/c/io/gets.htm‘¤c-/c/io/perror.htm‘²”|/c/io/printf.htm‘ÇÃx/c/io/putc.htm’‹—
- /io/flags.htm§Òs‰\
- /io/flush.htm§ÜO‹d/io/gcount.htm§è3‰D/io/get.htm§ñwa/io/getline.htm¨XŸ
- /io/good.htm¨®e/io/ignore.htm¨½}/io/io_flags.htm¨Íè/io/open.htm©µ6’M/io/peek.htm©È‰a/io/precision.htm©Ñd(/io/put.htm©á‰?/io/putback.htm©êK‰U/io/rdstate.htm©ô Š/io/read.htm©þ(”K
- /io/seekg.htmª’s‹n
- /io/seekp.htmªža‹
- /io/setf.htmª©k™A/io/sstream/ /io/sstream/constructors.htmªÃ, !/io/sstream/operators.htmªãMŒ?/io/sstream/rdbuf.htmªð‰/io/sstream/start.htmªù“/io/sstream/str.htm«ž1
- /io/start.htm««J¶G/io/sync_with_stdio.htm«â‰r
- /io/tellg.htm«ì‰3
- /io/tellp.htm«õ6•U/io/unsetf.htm¬‹‰
- /io/width.htm¬”
- /io/write.htm¬£.Š-
- ¬W÷ ~@Œ•S;ía±{7Òß«ÖýƒM#k´ï¨dý™+Ò«©w=UÒŠM+Åø°X`3>¥Ã yhÑvÐ9ñnVâ†Mçª"Ø%?z/:1ˆ<êÊkÓ
- ^íZÓ«rAÄcœGy_±à:Šø7
- ª)ÖŒ€ëÀÏ„&Àn
- $ܶÖÀï*©h~iB/0ã5çü½Ë[
- ±5ÇÅóÃÿdq2ÚR.8važ·øQkYa õ”}«Z>½5¥ä9—´ˆý2*ƒ†°Ê5Œ§w}3áÎÉÓKï¬ÑÄva† ù½®™]°0`óØW,ß@÷èK…f™
- ¾3U®ˆIô©Ò…#òÖ8Al/O¶q“íFŽ 3ßÊzw£öätÊ"¾pÍd—Å/Sk8SV÷Z\¾wvÚâ£^ðÕÄU´¬ÎÓiÃí» £3XÏãÿO,pEå˜ñ@üD„‘6xèÓ££bãÞò´Z}¿·í7!ÛdFöÈFxˆK
- ‡î æ½€ðKï-1“Np¹å˜TåäÝø½Àø.¨IŸ$U©RÒ >ÓsùÛôñÐz‡/õSCv¡pÕ[Piªw žjaÄS,Î.L‹Þzã~*(®à˜`µ[³ä§?’cÉáØ÷+ÙGéS²óÓ„ÚÑúÙ O›•©Øq‡þ"ÉVn…ïGáö€æcg„…
- uiìµ_öŒä×`HøõGk(VÊTKN©¿EXa„ẂîÒð+BÆšxI"^w PHÞQmè‘[I²ôÁ½6¬¼t4v+á>h4ÏàRëKh葱JÏ#ÿZâ~
- )¶×àÖÊ9㙯Z¿|-XŽKšù{§#_×ÄL<vŽIºE”WylèŸÔ"À]Ã_Ð!•KžšT
- Z:ß
- j*þsŽ
- ë5×"zòsnˆ|g(‹sV :‚¹“+>PÒÉî+’æÁ~¼]•ù¥|ác¦õÖ
- ¯•" q^ì´ž„ýÆœ2E<iÚüÄØÙ wuþÍ÷÷$ÄvË{ÁÝèÐKÙ>åš=YN&ƒ]¶Ñp'"ÃØÑœð] Öɇë%ø:EÏcÅP¾¹EZ[nÖ(‹ï „\¤ `]—:Ó}}@¡÷ã/?/œ)r¶
- «JË´ð_þD,pß^¬;áÞ1ÏpË¡iÎŽªâ~Õ.çf³¬ÔA«KçŽæ.ÙN'bfàž®Žõ%«é¢@kOp]-½#‘%Ƚ€\Æ…™4û˜Ô“NæOF®‹ÉùùÀ²,V¯ýù¥5Hú5ÃLõŒó}H~Ÿ©¶(¯É·w-¬¹úãÕ0@î×9[€Ú—…Ó*å§.ÌÐ Z/탯X]Ro\æ
- ê^´-}íBÐÑi¼*ø\ áÀDZŸNO'¡š³TéóÚDz`ÖA‰I”
- ¸îxø£Â{s—¨s ë'íGcjÆ'ÆK"€Ùãe5fƒ¹RÀ”-ÂóÏǸÙGã"zr¢‹R ¸ª“œ£³.[fz›?ˆõÆÂ#b
- ÿÓ;×uÁØÍ©£šx}ŒJ÷¯ÎÇ9Íûø^Õ{ßÊí9Æ+õs•g>)ì~‡3ÈèM
- k`Eå3r~u¸9þÉ3Ô4½ÏVÜ#ÓÿGÉØ£¼<WYsà’?yk‘ŠgÈÎcÌ
- Z:ß
- $ܶÖÀï*©h~iB/0ã5çü½Ë[
- ±5ÇÅóÃÿdq2ÚR.8važ·øQkYa õ”}«Z>½5¥ä9—´ˆý2*ƒ†°Ê5Œ§w}3áÎÉÓKï¬ÑÄva† ù½®™]°0`óØW,ß@÷èK…f™
- ¾3U®ˆIô©Ò…#òÖ8Al/O¶q“íFŽ 3ßÊzw£öätÊ"¾pÍd—Å/Sk8SV÷Z\¾wvÚâ£^ðÕÄU´¬ÎÓiÃí» £3XÏãÿO,pEå˜ñ@üD„‘6xèÓ££bãÞò´Z}¿·í7!ÛdFöÈFxˆK
- ‡î æ½€ðKï-1“Np¹å˜TåäÝø½Àø.¨IŸ$U©RÒ >ÓsùÛôñÐz‡/õSCv¡pÕ[Piªw žjaÄS,Î.L‹Þzã~*(®à˜`µ[³ä§?’cÉáØ÷+ÙGéS²óÓ„ÚÑúÙ O›•©Øq‡þ"ÉVn…ïGáö€æcg„…
- uiìµ_öŒä×`HøõGk(VÊTKN©¿EXa„ẂîÒð+BÆšxI"^w PHÞQmè‘[I²ôÁ½6¬¼t4v+á>h4ÏàRëKh葱JÏ#ÿZâ~
- )¶×àÖÊ9㙯Z¿|-XŽKšù{§#_×ÄL<vŽIºE”WylèŸÔ"À]Ã_Ð!•KžšT"
- ITSF ` ²V2b ý|ª{О É"æìý|ª{О É"æì` x T` Ì` þ a( ITSP T
- ÿÿÿÿ j’].!Ðù É"æìT ÿÿÿÿÿÿÿÿÿÿÿÿPMGL^ ÿÿÿÿ / /#IDXHDR„„q /#ITBITS /#STRINGS†²Ô/#SYSTEM …N¡5/#TOPICS„¤qË /#URLSTR…¨M‰G/#URLTBL„ð¸< /#WINDOWSö¿kL/$FIftiMainøÅY‹¿ /$OBJINSTø°•?/$WWAssociativeLinks/ /$WWAssociativeLinks/Propertyø°/$WWKeywordLinks/ /$WWKeywordLinks/BTreeöÁ7ÀL/$WWKeywordLinks/Dataø‚/$WWKeywordLinks/Mapø¯Z/$WWKeywordLinks/Propertyø¯v
- /ascii.htmŠÉF˜-/c/
- /c/all.htm‹ás±/c/date/ /c/date/asctime.htm’x
- /c/date/clock.htm£‹ /c/date/ctime.htm®ŽR/c/date/datime.htm¼`‰m/c/date/difftime.htmÆMŠ)/c/date/gmtime.htmÐv`/c/date/localtime.htmÞV” /c/date/mktime.htmòVŒH/c/date/setlocale.htmÿ’2/c/date/start.htmŽ‘P”:/c/date/strftime.htmަ
- £V/c/date/time.htmŽÉ`Žj/c/io/ /c/io/clearerr.htmŽØJŠm/c/io/fclose.htmŽã7‹/c/io/feof.htmŽîSŠl/c/io/ferror.htmŽù?ŠY/c/io/fflush.htm„—/c/io/fgetc.htm›)Œv/c/io/fgetpos.htm¨Œ/c/io/fgets.htm´ Ž
- /c/io/fopen.htmÂ-Ÿ/c/io/fprintf.htmá5“Z/c/io/fpurge.htmõ•/c/io/fputc.htmŠ"X/c/io/fputs.htm—zŒ0/c/io/fread.htm¤*4/c/io/freopen.htm´^/c/io/fscanf.htmÁoŽ/c/io/fseek.htmÏ~’P/c/io/fsetpos.htmâN‹C/c/io/ftell.htmî‰j/c/io/fwrite.htm÷{"/c/io/getc.htm‘…”t/c/io/getchar.htm‘šŠR/c/io/gets.htm‘¤c-/c/io/perror.htm‘²”|/c/io/printf.htm‘ÇÃx/c/io/putc.htm’‹—
- /io/flags.htm§Òs‰\
- /io/flush.htm§ÜO‹d/io/gcount.htm§è3‰D/io/get.htm§ñwa/io/getline.htm¨XŸ
- /io/good.htm¨®e/io/ignore.htm¨½}/io/io_flags.htm¨Íè/io/open.htm©µ6’M/io/peek.htm©È‰a/io/precision.htm©Ñd(/io/put.htm©á‰?/io/putback.htm©êK‰U/io/rdstate.htm©ô Š/io/read.htm©þ(”K
- /io/seekg.htmª’s‹n
- /io/seekp.htmªža‹
- /io/setf.htmª©k™A/io/sstream/ /io/sstream/constructors.htmªÃ, !/io/sstream/operators.htmªãMŒ?/io/sstream/rdbuf.htmªð‰/io/sstream/start.htmªù“/io/sstream/str.htm«ž1
- /io/start.htm««J¶G/io/sync_with_stdio.htm«â‰r
- /io/tellg.htm«ì‰3
- /io/tellp.htm«õ6•U/io/unsetf.htm¬‹‰
- /io/width.htm¬”
- /io/write.htm¬£.Š-
- ¬W÷ ~@Œ•S;ía±{7Òß«ÖýƒM#k´ï¨dý™+Ò«©w=UÒŠM+Åø°X`3>¥Ã yhÑvÐ9ñnVâ†Mçª"Ø%?z/:1ˆ<êÊkÓ
- ^íZÓ«rAÄcœGy_±à:Šø7
- ª)ÖŒ€ëÀÏ„&Àn
- $ܶÖÀï*©h~iB/0ã5çü½Ë[
- ±5ÇÅóÃÿdq2ÚR.8važ·øQkYa õ”}«Z>½5¥ä9—´ˆý2*ƒ†°Ê5Œ§w}3áÎÉÓKï¬ÑÄva† ù½®™]°0`óØW,ß@÷èK…f™
- ¾3U®ˆIô©Ò…#òÖ8Al/O¶q“íFŽ 3ßÊzw£öätÊ"¾pÍd—Å/Sk8SV÷Z\¾wvÚâ£^ðÕÄU´¬ÎÓiÃí» £3XÏãÿO,pEå˜ñ@üD„‘6xèÓ££bãÞò´Z}¿·í7!ÛdFöÈFxˆK
- ‡î æ½€ðKï-1“Np¹å˜TåäÝø½Àø.¨IŸ$U©RÒ >ÓsùÛôñÐz‡/õSCv¡pÕ[Piªw žjaÄS,Î.L‹Þzã~*(®à˜`µ[³ä§?’cÉáØ÷+ÙGéS²óÓ„ÚÑúÙ O›•©Øq‡þ"ÉVn…ïGáö€æcg„…
- uiìµ_öŒä×`HøõGk(VÊTKN©¿EXa„ẂîÒð+BÆšxI"^w PHÞQmè‘[I²ôÁ½6¬¼t4v+á>h4ÏàRëKh葱JÏ#ÿZâ~
- )¶×àÖÊ9㙯Z¿|-XŽKšù{§#_×ÄL<vŽIºE”WylèŸÔ"À]Ã_Ð!•KžšT
- Z:ß
- j*þsŽ
- ë5×"zòsnˆ|g(‹sV :‚¹“+>PÒÉî+’æÁ~¼]•ù¥|ác¦õÖ
- ¯•" q^ì´ž„ýÆœ2E<iÚüÄØÙ wuþÍ÷÷$ÄvË{ÁÝèÐKÙ>åš=YN&ƒ]¶Ñp'"ÃØÑœð] Öɇë%ø:EÏcÅP¾¹EZ[nÖ(‹ï „\¤ `]—:Ó}}@¡÷ã/?/œ)r¶
- «JË´ð_þD,pß^¬;áÞ1ÏpË¡iÎŽªâ~Õ.çf³¬ÔA«KçŽæ.ÙN'bfàž®Žõ%«é¢@kOp]-½#‘%Ƚ€\Æ…™4û˜Ô“NæOF®‹ÉùùÀ²,V¯ýù¥5Hú5ÃLõŒó}H~Ÿ©¶(¯É·w-¬¹úãÕ0@î×9[€Ú—…Ó*å§.ÌÐ Z/탯X]Ro\æ
- ê^´-}íBÐÑi¼*ø\ áÀDZŸNO'¡š³TéóÚDz`ÖA‰I”
- ¸îxø£Â{s—¨s ë'íGcjÆ'ÆK"€Ùãe5fƒ¹RÀ”-ÂóÏǸÙGã"zr¢‹R ¸ª“œ£³.[fz›?ˆõÆÂ#b
- ÿÓ;×uÁØÍ©£šx}ŒJ÷¯ÎÇ9Íûø^Õ{ßÊí9Æ+õs•g>)ì~‡3ÈèM
- k`Eå3r~u¸9þÉ3Ô4½ÏVÜ#ÓÿGÉØ£¼<WYsà’?yk‘ŠgÈÎcÌ
- $ܶÖÀï*©h~iB/0ã5çü½Ë[
- ±5ÇÅóÃÿdq2ÚR.8važ·øQkYa õ”}«Z>½5¥ä9—´ˆý2*ƒ†°Ê5Œ§w}3áÎÉÓKï¬ÑÄva† ù½®™]°0`óØW,ß@÷èK…f™
- ¾3U®ˆIô©Ò…#òÖ8Al/O¶q“íFŽ 3ßÊzw£öätÊ"¾pÍd—Å/Sk8SV÷Z\¾wvÚâ£^ðÕÄU´¬ÎÓiÃí» £3XÏãÿO,pEå˜ñ@üD„‘6xèÓ££bãÞò´Z}¿·í7!ÛdFöÈFxˆK
- ‡î æ½€ðKï-1“Np¹å˜TåäÝø½Àø.¨IŸ$U©RÒ >ÓsùÛôñÐz‡/õSCv¡pÕ[Piªw žjaÄS,Î.L‹Þzã~*(®à˜`µ[³ä§?’cÉáØ÷+ÙGéS²óÓ„ÚÑúÙ O›•©Øq‡þ"ÉVn…ïGáö€æcg„…
- uiìµ_öŒä×`HøõGk(VÊTKN©¿EXa„ẂîÒð+BÆšxI"^w PHÞQmè‘[I²ôÁ½6¬¼t4v+á>h4ÏàRëKh葱JÏ#ÿZâ~
- )¶×àÖÊ9㙯Z¿|-XŽKšù{§#_×ÄL<vŽIºE”WylèŸÔ"À]Ã_Ð!•KžšT
- $ܶÖÀï*©h~iB/0ã5çü½Ë[
- ±5ÇÅóÃÿdq2ÚR.8važ·øQkYa õ”}«Z>½5¥ä9—´ˆý2*ƒ†°Ê5Œ§w}3áÎÉÓKï¬ÑÄva† ù½®™]°0`óØW,ß@÷èK…f™
- ¾3U®ˆIô©Ò…#òÖ8Al/O¶q“íFŽ 3ßÊzw£öätÊ"¾pÍd—Å/Sk8SV÷Z\¾wvÚâ£^ðÕÄU´¬ÎÓiÃí» £3XÏãÿO,pEå˜ñ@üD„‘6xèÓ££bãÞò´Z}¿·í7!ÛdFöÈFxˆK
- ‡î æ½€ðKï-1“Np¹å˜TåäÝø½Àø.¨IŸ$U©RÒ >ÓsùÛôñÐz‡/õSCv¡pÕ[Piªw žjaÄS,Î.L‹Þzã~*(®à˜`µ[³ä§?’cÉáØ÷+ÙGéS²óÓ„ÚÑúÙ O›•©Øq‡þ"ÉVn…ïGáö€æcg„…
- uiìµ_öŒä×`HøõGk(VÊTKN©¿EXa„ẂîÒð+BÆšxI"^w PHÞQmè‘[I²ôÁ½6¬¼t4v+á>h4ÏàRëKh葱JÏ#ÿZâ~
- )¶×àÖÊ9㙯Z¿|-XŽKšù{§#_×ÄL<vŽIºE”WylèŸÔ"À]Ã_Ð!•KžšT
- Z:ß
- $ܶÖÀï*©h~iB/0ã5çü½Ë[
- ±5ÇÅóÃÿdq2ÚR.8važ·øQkYa õ”}«Z>½5¥ä9—´ˆý2*ƒ†°Ê5Œ§w}3áÎÉÓKï¬ÑÄva† ù½®™]°0`óØW,ß@÷èK…f™
- ¾3U®ˆIô©Ò…#òÖ8Al/O¶q“íFŽ 3ßÊzw£öätÊ"¾pÍd—Å/Sk8SV÷Z\¾wvÚâ£^ðÕÄU´¬ÎÓiÃí» £3XÏãÿO,pEå˜ñ@üD„‘6xèÓ££bãÞò´Z}¿·í7!ÛdFöÈFxˆK
- ‡î æ½€ðKï-1“Np¹å˜TåäÝø½Àø.¨IŸ$U©RÒ >ÓsùÛôñÐz‡/õSCv¡pÕ[Piªw žjaÄS,Î.L‹Þzã~*(®à˜`µ[³ä§?’cÉáØ÷+ÙGéS²óÓ„ÚÑúÙ O›•©Øq‡þ"ÉVn…ïGáö€æcg„…
- uiìµ_öŒä×`HøõGk(VÊTKN©¿EXa„ẂîÒð+BÆšxI"^w PHÞQmè‘[I²ôÁ½6¬¼t4v+á>h4ÏàRëKh葱JÏ#ÿZâ~
- )¶×àÖÊ9㙯Z¿|-XŽKšù{§#_×ÄL<vŽIºE”WylèŸÔ"À]Ã_Ð!•KžšT"
- #define nume ""
- #include<cmath>
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- #include<ctime>
- #include<algorithm>
- #include<iostream>
- #include<fstream>
- #include<vector>
- using namespace std;
- #ifndef INFOARENA
- #define DBG
- #endif
- #ifndef ONLINE_JUDGE
- ifstream fin (nume ".in");
- ofstream fout(nume ".out");
- #endif
- #ifdef DBG
- #define fout cout
- #endif
- //using namespace __gnu_cxx;
- //#include<ext/hash_map>
- //hash_multimap<int,int> H;
- //hash_map<char*,int> H;
- //using namespace tr1;
- //#include<tr1/unordered_set>
- //const double PI = M_PI;
- //const double EPS = 1e-9;
- #define foreach(it, v) for (typeof((v).begin()) it = (v).begin(),stop=(v).end(); it != stop; ++it)
- #define foreach_r(it, v) for (typeof((v).rbegin()) it = (v).rbegin(),stop=(v).rend(); it != stop; ++it)
- template<class T> inline void getmin(T& a,T& b){a=min(a,b);};
- template<class T> inline T min(T& a,T& b,T& c){return min(a,min(b,c));};
- template<class T>void dbg(T x, bool newline=false){
- #ifdef DBG
- cerr<<x<<((newline)?'\n':' ');
- #endif
- }
- template<class T>void dbg(T v[], int n, bool p=false){for(int i=p;i<n+p;++i)dbg(v[i]);dbg("",true);dbg("",true);}
- template<class T>void dbg(T* a, int n, int m, bool p=false){for(int i=p;i<n+p;++i,dbg("",true))for(int j=p;j<m+p;++j)dbg(a[i][j]);dbg("",true);}
- #define NMAX
- int n;
- int main()
- {
- return 0;
- }
- /////////////////////////////////////////////
- /////////////////////////////////////////////
- //OLD
- /////////////////////////////////////////////
- /////////////////////////////////////////////
- #ifndef INFOARENA
- #define DBG
- #endif
- #define nume "password"
- #include<cstdio>
- #include<iostream>
- #include<fstream>
- #include<vector>
- #include<cstring>
- #include<string>
- #include<sstream>
- #include<cstdlib>
- #include<cmath>
- #include<queue>
- #include<set>
- #include<map>
- #include<cassert>
- #include<ctime>
- #include<list>
- #include<algorithm>
- using namespace std;
- using namespace __gnu_cxx;
- //#define _PARSARE_
- #ifdef _PARSARE_
- #define DIM 8192
- char ax[DIM+16];
- int _idx;
- template<class T>
- inline void cit(T& x)
- {
- x=0;
- while((ax[_idx]<'0' || ax[_idx]>'9') && (ax[_idx]!='-'))
- if(++_idx==DIM)fread(ax, 1, DIM, stdin), _idx=0;
- int neg=0;
- if(ax[_idx]=='-') {
- neg=1;
- if(++_idx==DIM)fread(ax, 1, DIM, stdin),_idx=0;
- }
- while(ax[_idx]>='0' && ax[_idx]<='9') {
- x=x*10+ax[_idx]-'0';
- if(++_idx==DIM)fread(ax,1, DIM, stdin),_idx=0;
- }
- if(neg) x=-x;
- }
- #else
- #ifndef ONLINE_JUDGE
- ifstream fin (nume ".in");
- #endif
- #endif //_PARSARE_
- #ifndef ONLINE_JUDGE
- ofstream fout(nume ".out");
- #endif
- #ifdef DBG
- #define fout cout
- #ifdef ONLINE_JUDGE
- #define fin cin
- #endif
- #endif
- //// hash-uri
- //#include<ext/hash_map>
- //hash_multimap<int,int> H;
- //hash_map<char*,int> H;
- //const double PI = acos(-1.0);
- //const double EPS = 1e-9;
- #define foreach(it, v) for (typeof((v).begin()) it = (v).begin(),stop=(v).end(); it != stop; ++it)
- #define foreach_r(it, v) for (typeof((v).rbegin()) it = (v).rbegin(),stop=(v).rend(); it != stop; ++it)
- template<class T> inline void Swap(T& a,T& b){a^=b,b^=a,a^=b;}
- int n,m;
- int main()
- {
- #ifdef _PARSARE_
- #ifndef ONLINE_JUDGE
- freopen(nume ".in","r",stdin);
- #endif
- cit(n);
- #endif
- #ifndef DBG
- #ifndef ONLINE_JUDGE
- fout.close();
- #endif
- #endif
- return 0;
- }
- ////////////////////////////////////////////////
- //OJI
- #define nume ""
- #include<cstdio>
- #include<iostream>
- #include<fstream>
- #include<vector>
- #include<queue>
- #include<algorithm>
- using namespace std;
- //ofstream fout(nume ".out");
- #define foreach(it, v) for (typeof((v).begin()) it = (v).begin(),stop=(v).end(); it != stop; ++it)
- int n;
- int main()
- {
- freopen(nume ".in","r",stdin);
- freopen(nume ".out","w",stdout);
- #ifdef _PARSARE_
- cit(n);
- #endif
- scanf("%d",&n);
- // printf("%I64d",sol);
- // printf("%lld",sol);
- // printf("%u",sol);//unsigned
- // printf("%h",sol);//short
- return 0;
- }
- /*
- #include<set>
- #include<map>
- #include<ctime>
- #include<list>
- #include<cstring>
- #include<string>
- #include<sstream>
- #include<cstdlib>
- //#define _PARSARE_
- #ifdef _PARSARE_
- #define DIM 8192
- char ax[DIM+16];
- int _idx;
- template<class T>
- inline void cit(T &x)
- {
- x=0;
- while((ax[_idx]<'0' || ax[_idx]>'9') && (ax[_idx]!='-'))
- if(++_idx==DIM)fread(ax, 1, DIM, stdin), _idx=0;
- int neg=0;
- if(ax[_idx]=='-') {
- neg=1;
- if(++_idx==DIM)fread(ax, 1, DIM, stdin),_idx=0;
- }
- while(ax[_idx]>='0' && ax[_idx]<='9') {
- x=x*10+ax[_idx]-'0';
- if(++_idx==DIM)fread(ax,1, DIM, stdin),_idx=0;
- }
- if(neg) x=-x;
- }
- #else
- //ifstream fin (nume ".in");
- #endif //_PARSARE_
- inline void bellmanford()
- {
- memset(d,0x3f,sizeof(d));
- d[1]=0;
- Q.clear();
- Q.push(1);
- in_queue[1]=true;
- cnt_in_queue[1]=1;
- while(!Q.empty()) {
- int nod=Q.front();
- Q.pop();
- in_queue[nod]=false;
- foreach(it,G[nod]) {
- if( d[it->first]>d[nod]+it->second ) {
- d[it->first]=d[nod]+it->second;
- if(!in_queue[it->first]){
- Q.push(it->first);
- in_queue[it->first]=true;
- if(cnt_in_queue[it->first]++>n) {
- fout<<"Ciclu negativ!\n";
- exit(0);
- }
- }
- }
- }
- }
- }
- */
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //memoizarea unei functii recursive cu map
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Un map este foarte util pentru a memoiza o functie recursiva.
- int my_func(int t)
- {
- // e recursiva si pura (rezultatul depinde doar de parametri)
- return result;
- }
- Se transforma in:
- map <int, int> cache;
- int my_func(int t)
- {
- map <int, int> :: const_iterator it = cache.find(t);
- if(it != cache.end())
- return it->second;
- // corpul vechi
- return cache[t] = result;
- }
- //(in loc de int poate sa fie orice tip)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //binary search (fast)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- int binary_search(int[] A, int x)
- {
- int i, step, N = A.length;
- for (step = 1; step < N; step <<= 1)
- ;
- for (i = 0; step; step >>= 1)
- if (i + step < N && A[i + step] <= x)
- i += step;
- if (A[i] == x)
- return i;
- else
- return -1;
- }
- //////////////////////////////////////////////////////////////
- //binary search (very good)
- //////////////////////////////////////////////////////////////
- int binary_search(int[] A, int x)
- {
- int dr = A.length, st = -1, mid; //initializare!!! setam pe dr si st inafara sirului, astfel invariantul e indeplinit si nu trebuie sa tratam cazuri speciale.
- while (dr - st > 1) { //conditia de continuare a buclei e dr - st > 1. Invariantul ales face ca dr si st sa fie tot timpul distincte. La fiecare pas distanta intre dr si st se injumatateste, iar cand dr si st ajung consecutive ca pozitii in sir putem lua o decizie.
- mid = st + (dr - st) / 2; //((unsigned int)st + (unsigned int)dr)) >> 1; //mid va fi tot timpul intre st si dr.
- if (A[mid] < x)
- st = mid;
- else // if(A[mid] >= x)
- dr = mid;
- }
- if (dr == A.length || A[dr] != x) // cand ultimul element din sir e mai mic decat x, st = A.length - 1 si dr = A.length
- return -1; // sau cand dr este undeva in interiorul sirului, A[st] < x < A[dr]
- else //x e in sir
- return dr;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //scmax O(NlgN)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- int n, v[100003], best[100003], poz[100003], maxim, k, L[100003], nr;
- void afis(int i)
- {
- if (poz[i] > 0) afis(poz[i]);
- printf("%d ",v[i]);
- }
- int caut_bin(int x)
- {
- int st, dr, m;
- st = 0;
- dr = nr;
- while (st <= dr) {
- m = ((unsigned int)st + (unsigned int)dr)>>1;
- if (v[L[m]] < x && v[L[m+1]] >= x)
- return m;
- else if (v[L[m+1]] < x)
- st = m + 1;
- else
- dr = m - 1;
- }
- return nr;
- }
- int main()
- {
- //...
- nr = 1;
- L[0] = 0;
- L[1] = 1;
- best[1] = 1;
- for(i=2; i<=n; ++i) {
- int p = caut_bin(v[i]);
- best[i] = p+1;
- poz [i] = L[p];
- L [p+1] = i;
- if(best[i]>nr) {
- nr=best[i];
- pozmax=i;
- }
- }
- printf("%d\n",nr);
- afis(pozmax);
- //...
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //scmax O(N lg K) -- algorithmist
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <vector>
- using namespace std;
- /* Finds longest strictly increasing subsequence. O(n log k) algorithm. */
- void find_lis(vector<int> &a, vector<int> &b)
- {
- vector<int> p(a.size());
- int u, v;
- if (a.empty()) return;
- b.push_back(0);
- for (size_t i = 1; i < a.size(); i++) {
- // If next element a[i] is greater than last element of current longest subsequence a[b.back()], just push it at back of "b" and continue
- if (a[b.back()] < a[i]) {
- p[i] = b.back();
- b.push_back(i);
- continue;
- }
- // Binary search to find the smallest element referenced by b which is just bigger than a[i]
- // Note : Binary search is performed on b (and not a). Size of b is always <=k and hence contributes O(log k) to complexity.
- for (u = 0, v = b.size()-1; u < v;) {
- int c = (u + v) / 2;
- if (a[b[c]] < a[i]) u=c+1;
- else v=c;
- }
- // Update b if new value is smaller then previously referenced value
- if (a[i] < a[b[u]]) {
- if (u > 0) p[i] = b[u-1];
- b[u] = i;
- }
- }
- for (u = b.size(), v = b.back(); u--; v = p[v]) b[u] = v;
- }
- /* Example of usage: */
- #include <cstdio>
- int main()
- {
- int a[] = { 1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7 };
- vector<int> seq(a, a+sizeof(a)/sizeof(a[0])); // seq : Input Vector
- vector<int> lis; // lis : Vector containing indexes of longest subsequence
- find_lis(seq, lis);
- //Printing actual output
- for (size_t i = 0; i < lis.size(); i++)
- printf("%d ", seq[lis[i]]);
- printf("\n");
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //scmax O(N lg N) -- AIB
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include <algorithm>
- using namespace std;
- #define NMax 100005
- int N, Res[NMax], v[NMax], lst[NMax], D[NMax], AIB[NMax], bst, up[NMax];
- void update(int x, int ind)
- {
- for (; x <= N; x += x^(x-1) & x)
- if (D[ind] > D[AIB[x]])
- AIB[x] = ind;
- }
- int query(int x)
- {
- int mx = 0;
- for (; x; x -= x^(x-1) & x)
- if (D[AIB[x]] > D[mx])
- mx = AIB[x];
- return mx;
- }
- int main(void)
- {
- int i, h = 1;
- freopen("scmax.in", "r", stdin);
- freopen("scmax.out", "w", stdout);
- scanf("%d", &N);
- for (i = 1; i <= N; ++i) {
- scanf("%d", &v[i]);
- Res[i] = lst[i] = v[i];
- }
- sort(lst+1, lst+N+1);
- for (i = 2; i <= N; ++i)
- if (lst[i] != lst[h])
- lst[++h] = lst[i];
- for (i = 1; i <= N; ++i)
- v[i] = lower_bound(lst+1, lst+h+1, v[i])-lst;
- for (i = 1; i <= N; ++i) {
- up[i] = query(v[i]-1);
- D[i] = D[up[i]] + 1;
- update(v[i], i);
- }
- for (i = 1; i <= N; ++i)
- if (D[bst] < D[i])
- bst = i;
- printf("%d\n", D[bst]);
- for (h = 0, i = bst; i; i = up[i])
- lst[++h] = Res[i];
- for (i = h; i; --i)
- printf("%d ", lst[i]);
- printf("\n");
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //scmax O(N lg K) -- by me, Laur Ion :>
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //scmax cu/fara upper_bound by Laur Ion
- //Complexitate: O(N lg K) | unde K e lungimea scmax (cautarea binara este facuta pe Q (nu v) a carui lungime este mereu <= K => O(lg K) complexitate)
- #include<cstdio>
- #include<iostream>
- #include<fstream>
- #include<vector>
- #include<cstring>
- #include<string>
- #include<sstream>
- #include<iterator>
- #include<cstdlib>
- #include<queue>
- #include<set>
- #include<map>
- #include<algorithm>
- #include<cassert>
- #define filein "scmax.in"
- #define fileout "scmax.out"
- using namespace std;
- ifstream fin(filein);
- ofstream fout(fileout);
- int n;
- //vector<int> G[100000+10];
- #define NMax 100005
- int v[NMax], prev[NMax];
- vector<int> Q; //vector de pozitii ale scmax
- bool cmp(int val, int poz)
- {
- return val < v[poz];
- }
- inline void afis(int poz)
- {
- if(poz == 0) {
- return;
- }
- afis(prev[poz]);
- fout<<v[poz]<<' ';
- }
- inline int bin_search (int val)
- {
- int st=-1,dr=Q.size()-1,m;
- while(dr-st>1) {
- m = ((unsigned int)st + (unsigned int)dr) >> 1;
- if(v[Q[m]] < val)
- st=m;
- else
- dr=m;
- }
- return dr;
- }
- int main()
- {
- fin>>n;
- for(int i=1; i<=n; ++i)
- fin>>v[i];
- Q.push_back(1);
- // memset(prev,0xff,sizeof(prev));
- for(int i=2; i<=n; ++i) {
- if (v[i] > v[Q.back()]) { //daca elementul curent e mai mare decat ultimul element a scmax curente (v[Q.back])
- prev[i] = Q.back(); //se adauga la capatul lui Q si se continua
- Q.push_back(i);
- continue;
- }
- //cauta cel mai mic element referentiat de Q care e mai mare decat v[i]
- int p = bin_search(v[i]);
- assert(p>=0);
- if (v[i] < v[Q[p]]) {
- if (p > 0)
- prev[i] = Q[p-1];
- Q[p] = i;
- }
- //varianta cu upper_bound: //problema e ca upper bound merge doar pt subsir crescator (nestrict, cu <=)
- // vector<int>::iterator it = upper_bound(Q.begin(), Q.end(), v[i], cmp); //
- // if(it != Q.begin() && v[*(it-1)] == v[i]) //upper_bound face <= cumva deci trebuie sa verificam si sa nu fie elemente egale
- // continue;
- // int _pit=it-Q.begin();
- // if(v[i]<v[*it]) {
- // if(it != Q.begin())
- // prev[i] = *(it-1);
- // *it = i;
- // }
- }
- fout<<Q.size()<<'\n';
- afis(Q.back());
- fout<<'\n';
- fout.close();
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //NUMERE MARI
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- inline void suma( short* A, short* B, short* C)
- {
- int i,t=0;
- for(i=1; i<=A[0]||i<=B[0]||t; ++i,t/=10) {
- C[i]=(t+=A[i]+B[i])%10;
- }
- C[0]=i-1;
- }
- inline void scadere(short A[], short B[])
- {
- int i, t = 0;
- for (i = 1; i <= A[0]; i++) {
- A[i] -= ((i <= B[0]) ? B[i] : 0);
- A[i] -= t;
- if(A[i]<0) { //in loc de: A[i] += (t = A[i] < 0) * 10;
- t=1;
- A[i]+=10;
- } else
- t=0;
- while( A[0] > 1 && !A[A[0]] ) //scap de zero-uri
- A[0]--;
- }
- }
- inline void impartire(short* A, int B) {
- int i,t=0;
- for(i=A[0]; i>0; --i,t%=B)//in reverse
- A[i]=(t=t*10 + A[i])/B;
- while( A[0] > 1 && !A[A[0]] ) //scap de zero-uri
- A[0]--;
- }
- inline int modulo(short* A, int B) {
- int i,t=0;
- for(i=A[0]; i>0; --i)//in reverse
- t=(t*10 + A[i])%B;
- return t;
- }
- inline void inmultire(short* A, int B) {
- int i,t=0;
- for(i=1; i<=A[0] || t; ++i,t/=10)
- A[i]=(t+=A[i]*B)%10;
- A[0]=i-1;
- }
- inline void inmultire(short* A, short* B) {
- short C[50000];
- int i,j,t;
- memset(C,0,sizeof(C));
- for(i=1; i<=A[0]; ++i) {
- for(j=1; j<=B[0] || t; ++j,t/=10)
- C[i+j-1]=(t+=C[i+j-1]+A[i]*B[j])%10;
- C[0]=max(C[0],i+j-2);//dimensiunea rezultatului creste
- }
- memcpy(A,C,sizeof(C));
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Librarie numere mari (trimbitas)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <iostream>
- using namespace std;
- int n;
- #include <stdio.h>
- #include <string.h>
- class Huge {
- public:
- int Semn;
- int Cont;
- int V[10000];
- Huge() {
- *this = 0;
- }
- Huge& operator =(long long Val) {
- this->V[0] = this->Cont = 0;
- if (Val < 0) {
- Val = -Val;
- this->Semn = -1;
- } else {
- this->Semn = 1;
- }
- for (; Val; ) {
- this->V[this->Cont++] = (int)(Val % 100000000);
- Val -= Val % 100000000;
- Val /= 100000000;
- }
- if (this->Cont) --this->Cont;
- return *this;
- }
- Huge& operator =(const Huge& B) {
- this->Cont = B.Cont;
- this->Semn = B.Semn;
- memcpy(this->V, B.V, sizeof(int) * (this->Cont + 1));
- return *this;
- }
- /*returneaza 1 daca A>B
- * 0 daca A=B
- * -1 daca A<B
- */
- int Comparare(const Huge &A, const Huge &B) const {
- if (A.Semn != B.Semn) {
- if (A.Semn==1) return 1;
- else return -1;
- } else {
- if (A.Cont > B.Cont) {
- if (A.Semn == 1) return 1;
- else return -1;
- } else if (A.Cont < B.Cont) {
- if (A.Semn == 1) return -1;
- else return 1;
- } else {
- int i;
- for (i = A.Cont; A.V[i] == B.V[i] && i >= 0; --i);
- if (i >= 0) {
- if (A.V[i] > B.V[i]) {
- if (A.Semn == 1) return 1;
- else return -1;
- } else {
- if (A.Semn == 1) return -1;
- else return 1;
- }
- } else {
- return 0;
- }
- }
- }
- }
- bool operator >(const Huge& B) const {
- return Comparare(*this, B) == 1;
- }
- bool operator <(const Huge& B) const {
- return Comparare(*this, B) == -1;
- }
- bool operator >=(const Huge& B) const {
- return Comparare(*this, B) != -1;
- }
- bool operator <=(const Huge& B) const {
- return Comparare(*this, B) != 1;
- }
- bool operator ==(const Huge& B) const {
- return Comparare(*this, B) == 0;
- }
- bool operator !=(const Huge& B) const {
- return Comparare(*this, B) != 0;
- }
- bool operator >(const long long& b) const {
- Huge B;
- B = b;
- return Comparare(*this, B) == 1;
- }
- bool operator <(const long long& b) const {
- Huge B;
- B = b;
- return Comparare(*this, B) == -1;
- }
- bool operator >=(const long long& b) const {
- Huge B;
- B = b;
- return Comparare(*this, B) != -1;
- }
- bool operator <=(const long long& b) const {
- Huge B;
- B = b;
- return Comparare(*this, B) != 1;
- }
- bool operator ==(const long long& b) const {
- Huge B;
- B = b;
- return Comparare(*this, B) == 0;
- }
- bool operator !=(const long long& b) const {
- Huge B;
- B = b;
- return Comparare(*this, B) != 0;
- }
- Huge operator +() const {
- return *this;
- }
- Huge operator -() const {
- Huge A = *this;
- A.Semn = -A.Semn;
- return A;
- }
- Huge operator -(Huge C);
- Huge operator +(Huge C);
- Huge operator -(long long c) {
- Huge C;
- C = c;
- return *this - C;
- }
- Huge operator +(long long c) {
- Huge C;
- C = c;
- return *this + C;
- }
- Huge& operator ++() {
- int i;
- if (this->Semn == 1) {
- ++this->V[0];
- for (i = 0; this->V[i] == 100000000; ++i) {
- this->V[i] = 0;
- ++this->V[i + 1];
- }
- if (this->Cont < i) {
- this->Cont = i;
- }
- } else {
- --this->V[0];
- for (i = 0; this->V[i] == -1; ++i) {
- this->V[i] += 100000000;
- --this->V[i + 1];
- }
- if (this->V[this->Cont] == 0) {
- --this->Cont;
- }
- if (this->Cont == -1) {
- this->Semn = 1;
- this->Cont = 0;
- }
- }
- return *this;
- }
- Huge& operator --() {
- int i;
- if (this->Semn == -1) {
- ++this->V[0];
- for (i = 0; this->V[i] == 100000000; ++i) {
- this->V[i] = 0;
- ++this->V[i + 1];
- }
- if (this->Cont < i) {
- this->Cont = i;
- }
- } else {
- if (this->Cont == 0 && this->V[0] == 0) {
- this->Semn = -1;
- this->V[0] = 1;
- } else {
- --this->V[0];
- for (i = 0; this->V[i] == -1; ++i) {
- this->V[i] += 100000000;
- --this->V[i + 1];
- }
- if (this->V[this->Cont] == 0) {
- --this->Cont;
- }
- if (this->Cont == -1) {
- this->Cont = 0;
- }
- }
- }
- return *this;
- }
- Huge operator *(int Val) const {
- Huge A;
- if (Val < 0) {
- Val = -Val;
- if (this->Semn == -1) A.Semn = 1;
- else A.Semn = -1;
- } else {
- A.Semn = this->Semn;
- }
- int i;
- long long tmp;
- for (i = 0; i <= this->Cont + 1; ++i) {
- A.V[i] = 0;
- }
- for (i = 0; i <= this->Cont; ++i) {
- tmp = (long long)this->V[i] * Val + A.V[i];
- A.V[i] = (int)(tmp % 100000000);
- //A.V[i + 1] = (tmp - A.V[a]) / 100000000;
- A.V[i + 1] = (int)(tmp / 100000000);
- }
- if (A.V[this->Cont + 1]) {
- A.Cont = this->Cont + 1;
- } else {
- A.Cont = this->Cont;
- }
- return A;
- }
- Huge operator *(const Huge& C) const {
- Huge A;
- if (this->Semn == 1) {
- A.Semn = C.Semn;
- } else {
- if (C.Semn == -1) A.Semn = 1;
- else A.Semn = -1;
- }
- Huge Tmp;
- int i, j;
- for (i = 0; i <= this->Cont + C.Cont + 1; ++i) {
- A.V[i] = 0;
- }
- for (i = 0; i <= C.Cont; ++i) {
- Tmp = (*this) * C.V[i];
- for(j = 0; j <= Tmp.Cont; ++j) {
- A.V[i + j] += Tmp.V[j];
- A.Cont = i + j;
- if (A.V[i + j] >= 100000000) {
- A.V[i + j] -= 100000000;
- ++A.V[i + j + 1];
- A.Cont = i + j + 1;
- }
- }
- }
- return A;
- }
- Huge operator /(int Val) const {
- Huge A;
- if (Val < 0) {
- Val = -Val;
- if (this->Semn == -1) A.Semn = 1;
- else A.Semn = -1;
- } else {
- A.Semn = this->Semn;
- }
- int i;
- long long tmp1, tmp2;
- tmp1 = this->V[this->Cont];
- for (i = this->Cont; i >= 0; --i) {
- tmp2 = tmp1 % Val;
- tmp1 -= tmp2;
- A.V[i] = (int)(tmp1 / Val);
- if (i) tmp1 = tmp2 * 100000000 + this->V[i - 1];
- }
- if (A.V[this->Cont]) {
- A.Cont = this->Cont;
- } else {
- A.Cont = this->Cont - 1;
- }
- return A;
- }
- int operator %(int Val) const {
- long long tmp = 0;
- int i;
- for(i = this->Cont; i >= 0; --i) {
- tmp *= 100000000;
- tmp += this->V[i];
- tmp %= Val;
- }
- return (int)tmp;
- }
- Huge& operator +=(Huge B) {
- *this = *this + B;
- return *this;
- }
- Huge& operator -=(Huge B) {
- *this = *this - B;
- return *this;
- }
- Huge& operator +=(long long B) {
- *this = *this + B;
- return *this;
- }
- Huge& operator -=(long long B) {
- *this = *this - B;
- return *this;
- }
- Huge& operator *=(Huge& B) {
- *this = *this * B;
- return *this;
- }
- Huge& operator *=(int B) {
- *this = *this * B;
- return *this;
- }
- Huge& operator /=(int B) {
- *this = *this / B;
- return *this;
- }
- void afisare(FILE *output) {
- int i;
- if (this->Semn == -1) fprintf(output, "-");
- fprintf(output, "%d", this->V[this->Cont]);
- for(i = this->Cont - 1; i >= 0; --i) {
- fprintf(output, "%.8d", this->V[i]);
- }
- }
- void afisare() {
- afisare(stdout);
- }
- void citire(FILE *input) {
- int Nr0;
- char Nr[1000];
- int stop;
- int i, j;
- int tmp, tmpc;
- fscanf(input, "%s", Nr);
- Nr0 = strlen(Nr);
- if (Nr[0] == '-') {
- stop = 1;
- this->Semn = -1;
- } else {
- stop = 0;
- this->Semn = 1;
- }
- this->V[this->Cont = 0] = 0;
- for(i = Nr0 - 1; i >= stop; ) {
- tmp = 0;
- tmpc = 0;
- for(j = 1; j <= 8 && i >= stop; ++j) {
- tmp *= 10;
- tmp += Nr[i] - '0';
- --i;
- ++tmpc;
- }
- for(j = 1; j <= tmpc; ++j) {
- this->V[this->Cont] *= 10;
- this->V[this->Cont] += tmp % 10;
- tmp /= 10;
- }
- this->V[++this->Cont] = 0;
- }
- if (this->V[this->Cont] == 0) {
- --this->Cont;
- }
- if (this->Cont == 0 && this->V[0] == 0 && this->Semn == -1) this->Semn = 0;
- }
- void citire() {
- citire(stdin);
- }
- };
- Huge Huge::operator +(Huge C) {
- Huge A;
- if ((this->Semn == -1 && C.Semn== -1) ||
- (this->Semn == 1 && C.Semn== 1)) {
- A.Semn = this->Semn;
- int i;
- int tmp;
- int MAX = this->Cont + 1;
- if (MAX < C.Cont + 1) {
- MAX = C.Cont + 1;
- }
- for (i = 0; i <= MAX; ++i) {
- A.V[i] = 0;
- }
- for(i = this->Cont + 1; i <= MAX; ++i) {
- this->V[i] = 0;
- }
- for(i = C.Cont + 1; i <= MAX; ++i) {
- C.V[i] = 0;
- }
- for(i = 0; i <= MAX - 1; ++i) {
- tmp = A.V[i] + this->V[i] + C.V[i];
- //A.V[i] = tmp % 100000000;
- //A.V[i + 1] = tmp / 100000000;
- if (tmp < 100000000) {
- A.V[i] = tmp;
- } else {
- A.V[i] = tmp - 100000000;
- A.V[i + 1] = 1;
- }
- }
- if (A.V[MAX]){
- A.Cont = MAX;
- } else {
- A.Cont = MAX - 1;
- }
- } else {
- if (this->Semn == -1) {
- this->Semn = 1;
- A = C - *this;
- this->Semn = -1;
- } else {
- C.Semn = 1;
- A = *this - C;
- C.Semn = -1;
- }
- }
- return A;
- }
- Huge Huge::operator -(Huge C) {
- Huge A;
- if (this->Semn == -1 && C.Semn == -1) {
- this->Semn = 1;
- C.Semn = 1;
- A = C - *this;
- this->Semn = -1;
- C.Semn = -1;
- } else if (this->Semn == -1 && C.Semn == 1) {
- this->Semn = 1;
- A = *this + C;
- this->Semn = -1;
- A.Semn = -1;
- } else if (this->Semn == 1 && C.Semn == -1) {
- C.Semn = 1;
- A = *this + C;
- C.Semn = -1;
- } else if (this->Semn == 1 && C.Semn == 1) {
- if (*this >= C) {
- A.Semn = 1;
- int i;
- int tmp;
- int MAX = this->Cont + 1;
- if (MAX < C.Cont + 1) {
- MAX = C.Cont + 1;
- }
- for (i = 0; i <= MAX; ++i) {
- A.V[i] = 0;
- if (i > this->Cont) this->V[i] = 0;
- if (i > C.Cont) C.V[i] = 0;
- }
- for (i = 0; i <= MAX - 1; ++i) {
- tmp = A.V[i] + this->V[i] - C.V[i];
- if (tmp >= 0) {
- A.V[i] = tmp;
- } else {
- A.V[i] = tmp + 100000000;
- A.V[i + 1] = -1;
- }
- }
- for (A.Cont = MAX; !A.V[A.Cont] && A.Cont; --A.Cont);
- } else {
- A = C - *this;
- A.Semn = -1;
- }
- }
- return A;
- }
- Huge r;
- int fr[2000005];
- int gcd(int a,int b) {
- for(int c;b;c=a%b,a=b,b=c);
- return a;
- }
- static inline Huge put(int n) {
- Huge r,b;
- b=2;r=1;
- if(n==0) {
- r=1;
- return r;
- }
- if(n==1) return b;
- for(;n;) {
- if(n&1)r*=b;
- b*=b;
- n>>=1;
- }
- return r;
- }
- int main() {
- //freopen("asd.in","r",stdin);
- cin>>n;
- for(int i=1; i<=n; ++i) ++fr[gcd(i,n)];
- for(int i=1; i<=n; ++i) if(fr[i]) {
- r+=(put(i)*fr[i]);
- }
- r/=n;
- r.afisare();
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Clasa numere mari (SpiderMan) 1
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- /*
- Colectia personala de operatii pe numere mari - C++ ( classes )
- Implementate de Robert Simoiu
- Incluzand extragerea radacinii patrate cu oricate zecimale
- */
- # include <cmath>
- # include <cstdio>
- # include <cstring>
- # include <vector>
- using namespace std ;
- /*
- precizare :
- 1. Daca vreti sa faceti a = b + c, in loc de a += b , trebuie in loc de void operator += ( ... )
- sa faceti Mare operator + ( ... ) , si sa returnati un vector Mare ( exemplu prima functie, Mare operator + ( Mare& ) )
- 2. Pentru comparari, se poate face usor > si >=, doar schimband returnurile ( fals cu adevarat, si invers ), dar
- e de preferabil ca a > b sa se faca ca si b < a ( pentru a nu mai fi nevoie de introducerea unei noi comparari )
- */
- # define MAX 1000 // numarul de cifre
- # define verf( X, i ) ( i <= X[0] ? X[i] : 0 )
- # define A ( *this )
- class Mare : protected vector < int > {
- public :
- Mare ( ) ;
- Mare ( int ) ;
- Mare operator + ( Mare& ) ;
- void operator += ( Mare& ) ;
- void operator *= ( int ) ;
- void operator *= ( Mare& ) ;
- void operator -= ( Mare& ) ;
- bool operator < ( Mare& ) ;
- bool operator <= ( Mare& ) ;
- const Mare& operator = ( int ) ;
- const Mare& operator = ( Mare& ) ;
- void operator <<= ( int ) ;
- void operator >>= ( int ) ;
- void operator /= ( int ) ;
- void operator /= ( Mare& ) ;
- void radical_normal ( Mare&, int ) ;
- void radical_cb ( Mare& ) ;
- void afis_rad ( int ) ;
- } ;
- Mare :: Mare () { // A = 0
- this -> resize ( MAX ) ;
- }
- Mare :: Mare ( int X ) { // A = X
- this -> resize ( MAX ) ;
- for ( A[0] = 0; X ; X /= 10 ) {
- A[ ++A[0] ] = X % 10 ;
- }
- }
- Mare Mare :: operator + ( Mare &B ) { // C = A + B
- int i, t = 0; Mare C ;
- for ( i = 1; i <= A[0] || i <= B[0] || t; ++i, t /= 10 )
- C[i] = ( t += verf ( A, i ) + verf ( B, i ) ) % 10 ;
- C[0] = i - 1;
- return C ;
- }
- void Mare :: operator += ( Mare &B ) { // A += B
- int i, t = 0;
- for ( i = 1; i <= A[0] || i <= B[0] || t; ++i, t /= 10 )
- A[i] = ( t += verf ( A, i ) + verf ( B, i ) ) % 10 ;
- A[0] = i - 1;
- }
- void Mare :: operator *= ( int B ) { // A *= B
- int i, t = 0;
- for ( i = 1; i <= A[0] || t; ++i, t /= 10 )
- A[i] = ( t += verf ( A, i ) * B ) % 10 ;
- A[0] = i - 1;
- }
- const Mare& Mare :: operator = ( int X ) { // A = X
- for ( A[0] = 0; X ; X /= 10 )
- A[ ++A[0] ] = X % 10 ;
- return A ;
- }
- const Mare& Mare :: operator = ( Mare &B ) { // A = B
- for ( int i = 0; i <= B[0]; ++i )
- A[i] = B[i] ;
- return A ;
- }
- void Mare :: operator -= ( Mare &B ) { // A -= B, ∀ A ≥ B
- int t = 0;
- for ( int i = 1; i <= A[0]; ++i ) {
- t = ( A[i] -= verf ( B, i ) + t ) < 0 ;
- A[i] += t * 10 ;
- }
- for ( ; A[0] > 1 && !A[A[0]]; --A[0] ) ;
- }
- bool Mare :: operator < ( Mare &B ) { // A < B ?
- for ( ; A[0] && !A[ A[0] ] ; --A[0] ) ;
- for ( ; B[0] && !B[ B[0] ] ; --B[0] ) ;
- if ( A[0] < B[0] ) return true;
- else if ( A[0] > B[0] ) return false;
- for ( int i = A[0]; i > 0; --i )
- if ( A[i] < B[i] ) return true;
- else if ( A[i] > B[i] ) return false;
- return false;
- }
- bool Mare :: operator <= ( Mare &B ) { // A <= B ?
- for ( ; A[0] && !A[ A[0] ] ; --A[0] ) ;
- for ( ; B[0] && !B[ B[0] ] ; --B[0] ) ;
- if ( A[0] < B[0] ) return true;
- else if ( A[0] > B[0] ) return false;
- for ( int i = A[0]; i > 0; --i )
- if ( A[i] < B[i] ) return true;
- else if ( A[i] > B[i] ) return false;
- return true;
- }
- void Mare :: operator *= ( Mare &B ) { // A *= B
- int i, j, t ; Mare C ;
- for ( i = 1; i <= A[0]; ++i ) {
- for (t = 0, j = 1; j <= B[0] || t; j++, t /= 10)
- C[i + j - 1] = ( t += C[i + j - 1] + verf ( A, i ) * verf ( B, j ) ) % 10;
- if ( i + j - 2 > C[0] )
- C[0] = i + j - 2;
- }
- A = C ;
- }
- void Mare :: operator <<= ( int Count ) { // A *= ( Count * 10 )
- for ( int i = A[0]; i ; --i )
- A[i + Count] = A[i] ;
- for ( int i = 1; i <= Count; ++i )
- A[i] = 0 ;
- A[0] += Count ;
- }
- void Mare :: operator >>= ( int Count ) { // A /= ( Count * 10 )
- for ( int i = Count + 1; i <= A[0]; ++i ) {
- A[i - Count] = A[i] ;
- }
- A[0] -= Count ;
- }
- void Mare :: operator /= ( int B ) { // A /= B
- int t = 0;
- for ( int i = A[0]; i > 0; i--, t %= B )
- A[i] = ( t = t * 10 + A[i] ) / B ;
- for ( ; A[0] > 1 && !A[ A[0] ]; --A[0] ) ;
- }
- void Mare :: operator /= ( Mare &B ) { // A /= B
- Mare R ;
- for ( int i = A[0]; i ; --i ) {
- R <<= 1, R[1] = A[i] ;
- for ( A[i] = 0; B <= R ; ++A[i], R -= B ) ;
- }
- for ( ; !A[ A[0] ] && A[0] > 1 ; --A[0] ) ;
- }
- void Mare :: radical_cb ( Mare &B ) { // B = sqrt ( A ) ; doar parte intreaga
- Mare cnt, X ;
- for ( cnt = 1; cnt < A; cnt *= 2 ) ;
- for ( B[0] = 1 ; ! ( cnt[1] == 0 && cnt[0] == 1 ) ; cnt /= 2 ) {
- X = cnt, X += B, X *= X ;
- if ( X <= A )
- B += cnt ;
- }
- }
- void Mare :: radical_normal ( Mare &B, int nrzecimale ) {
- int AUX = 0, i, j = 1 ;
- Mare C, D, E, F, U ( 9 ), Z ( 1 ) ;
- if ( A[0] & 1 ) AUX = A[ A[0] ], i = A[0] - 1;
- else AUX = A[A[0]] * 10 + A[ A[0] - 1 ], i = A[0] - 2;
- int aux = static_cast < int > ( sqrt ( AUX ) ) ;
- B = aux ;
- if ( A[0] > 2 ) {
- AUX -= aux * aux;
- E = AUX, E <<= 1, F = A[i], E += F ;
- E <<= 1, F = A[i - 1], E += F ;
- C = E, F = B, F *= 2, E = F ;
- D = C, D >>= 1, D /= E ;
- if ( U < D ) {
- D = 9 ;
- }
- E <<= 1, E += D, E *= D ;
- while ( C < E )
- D -= Z, F = B, F *= 2, E = F, E <<= 1, E += D, E *= D ;
- C -= E ;
- B <<= 1, B += D ;
- } else {
- C = AUX - ( aux * aux ) ;
- }
- for ( i = i - 2; i > 0 || j <= nrzecimale ; i -= 2 ) {
- if ( i > 0 ) {
- E = A[i], F = 0, F <<= 1, F += E ;
- E = A[i - 1], F <<= 1, F += E ;
- } else {
- ++j, F = 0 ;
- }
- C <<= 2, C += F, F = B, F *= 2, E = F ;
- D = C, D >>= 1, D /= E ;
- if ( U < D ) {
- D = 9 ;
- }
- E <<= 1, E += D, E *= D ;
- while ( C < E )
- D -= Z, F = B, F *= 2, E = F, E <<= 1, E += D, E *= D ;
- C -= E ;
- B <<= 1, B += D ;
- }
- }
- void Mare :: afis_rad ( int nrzecimale ) { // afisarea radicalului
- for ( int i = A[0] ; i > nrzecimale ; --i )
- printf ( "%d", A[i] ) ;
- printf ( "." ) ;
- for ( int i = nrzecimale ; i ; --i ) {
- printf ( "%d", A[i] ) ;
- }
- }
- int main ( void ) {
- int a, b ;
- fscanf ( fopen ( "adunare.in", "r" ), "%d %d", &a, &b ) ;
- fprintf ( fopen ( "adunare.out", "w" ), "%d\n", a + b ) ;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Clasa numere mari (SpiderMan) 2
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- /*
- Colectia personala de operatii pe numere mari - C++ ( classes )
- Implementate de Robert Simoiu
- Incluzand extragerea radacinii patrate cu un numar finit de zecimale
- */
- # include <cmath>
- # include <cstdio>
- # include <cstring>
- # include <vector>
- using namespace std ;
- /*
- precizare :
- 1. Daca vreti sa faceti a = b + c, in loc de a += b , trebuie pus in loc de void operator += ( ... )
- Mare operator + ( ... ) , si sa returnati un vector Mare ( exemplu prima functie, Mare operator + ( Mare& ) )
- 2. Base inseamna baza si nbase numarul maxim de cifre al unui numar din baza base
- */
- # define MAX 100 // * nbase = numarul de cifre
- # define verf( X, i ) ( i <= X[0] ? X[i] : 0 )
- # define A ( *this )
- class Mare : protected vector < int > {
- static const int base = 1000000000, nbase = 9 ;
- public :
- Mare ( ) ;
- Mare ( int ) ;
- void operator = ( char* ) ;
- void operator += ( Mare& ) ;
- void operator *= ( int ) ;
- void operator *= ( Mare& ) ;
- void operator -= ( Mare& ) ;
- void operator <<= ( int ) ;
- void operator >>= ( int ) ;
- void operator /= ( int ) ;
- void operator /= ( Mare& ) ;
- void operator %= ( int ) ;
- void operator %= ( Mare& ) ;
- void operator ++ ( void ) ;
- void operator ++ ( int ) ;
- void operator -- ( void ) ;
- void operator -- ( int ) ;
- Mare operator + ( Mare& ) ;
- int zero ( void ) ;
- int comparare ( Mare& ) ;
- bool operator < ( Mare& ) ;
- bool operator <= ( Mare& ) ;
- bool operator > ( Mare& ) ;
- bool operator >= ( Mare& ) ;
- bool operator == ( Mare& ) ;
- bool operator != ( Mare& ) ;
- void operator |= ( Mare& ) ;
- void operator &= ( Mare& ) ;
- void operator ^= ( Mare& ) ;
- void afis ( void ) ;
- void afis_rad ( int ) ;
- void obtain ( int, int* ) ;
- void pow ( int ) ;
- void radical_cb ( Mare& ) ;
- void radical_normal ( Mare&, int ) ;
- void transform_2 ( int* ) ;
- void transform_10 ( int* ) ;
- void transform_210 ( int* ) ;
- } ;
- Mare :: Mare () { // A = 0
- this -> resize ( MAX ) ;
- }
- Mare :: Mare ( int X ) { // A = X
- this -> resize ( MAX ) ;
- for ( A[0] = 0; X ; X /= base ) {
- A[ ++A[0] ] = X % base ;
- }
- }
- void Mare :: operator = ( char *X ) { // A = X ( sir )
- A[0] = 0;
- if ( X ) {
- for ( int h = strlen ( X ) ; h > 0 ; h -= nbase ) {
- ++A[0] ;
- for ( int i = max ( 0, h - nbase ) ; i < h; ++i ) {
- A[ A[0] ] = A[ A[0] ] * 10 + X[i] - '0' ;
- }
- }
- }
- }
- void Mare :: operator += ( Mare &B ) { // A += B
- int i, t = 0;
- for ( i = 1; i <= A[0] || i <= B[0] || t; ++i, t /= base )
- A[i] = ( t += verf ( A, i ) + verf ( B, i ) ) % base ;
- A[0] = i - 1;
- }
- void Mare :: operator *= ( int B ) { // A *= B
- int i = 1;
- for ( long long t = 0; i <= A[0] || t; ++i, t /= base )
- A[i] = ( t += 1LL * verf ( A, i ) * B ) % base ;
- A[0] = i - 1;
- }
- void Mare :: operator *= ( Mare &B ) { // A *= B
- Mare C ;
- for ( int i = 1, j; i <= A[0]; ++i ) {
- long long t = 0 ;
- for ( j = 1; j <= B[0] || t; ++j, t /= base)
- C[i + j - 1] = ( t += C[i + j - 1] + 1LL * verf ( A, i ) * verf ( B, j ) ) % base;
- if ( i + j - 2 > C[0] )
- C[0] = i + j - 2;
- }
- A = C ;
- }
- void Mare :: operator -= ( Mare &B ) { // A -= B, ∀ A ≥ B
- int t = 0;
- for ( int i = 1; i <= A[0]; ++i ) {
- t = ( A[i] -= verf ( B, i ) + t ) < 0 ;
- A[i] += t * base ;
- }
- for ( ; A[0] > 1 && !A[A[0]]; --A[0] ) ;
- }
- void Mare :: operator <<= ( int Count ) { // A *= 10^Count
- if ( Count ) {
- if ( A.zero () ) A = 1 ;
- Mare sol = 10 ;
- sol.pow ( Count ), A *= sol ;
- }
- }
- void Mare :: operator >>= ( int Count ) { // A /= 10^Count
- if ( Count ) {
- Mare sol = 10 ;
- sol.pow ( Count ), A /= sol ;
- }
- }
- void Mare :: operator /= ( int B ) { // A /= B
- long long t = 0;
- for ( int i = A[0]; i > 0; i--, t %= B )
- A[i] = ( t = 1LL * t * base + A[i] ) / B ;
- for ( ; A[0] > 1 && !A[ A[0] ]; --A[0] ) ;
- }
- # define ck ( i / nbase + ( i % nbase != 0 ) )
- void Mare :: operator /= ( Mare &B ) { // A /= B
- int X[MAX * nbase];
- Mare R = 0, T ;
- A.transform_10 ( X ) ;
- fill_n ( A.begin () + 1, A[0], 0 ) ;
- for ( int i = X[0]; i ; --i ) {
- R *= R.zero () ? 0 : 10, T = X[i], R += T ;
- for ( A[ ck ] *= 10; B <= R ; ++A[ ck ], R -= B ) ;
- }
- for ( ; !A[ A[0] ] && A[0] > 1 ; --A[0] ) ;
- }
- void Mare :: operator %= ( int B ) { // A %= B
- long long t = 0;
- for ( int i = A[0]; i ; --i )
- t = ( 1LL * t * base + A[i] ) % B ;
- A = t ;
- }
- void Mare :: operator %= ( Mare &B ) { // A %= B
- int X[MAX * nbase] ; Mare R = 0, T, C ;
- A.transform_10 ( X ) ;
- fill_n ( C.begin () + 1, A[0], 0 ) ;
- for ( int i = X[0]; i ; --i ) {
- R *= R.zero () ? 0 : 10, T = X[i], R += T ;
- for ( C[ ck ] *= 10; B <= R ; ++C[ ck ], R -= B ) ;
- }
- A = R ;
- }
- # undef ck
- void Mare :: operator ++ ( void ) { // ++A
- Mare B = 1 ;
- A += B ;
- }
- void Mare :: operator ++ ( int ) { // A++
- ++A ;
- }
- void Mare :: operator -- ( void ) { // --A
- Mare B = 1 ;
- A -= B ;
- }
- void Mare :: operator -- ( int ) { // A--
- --A ;
- }
- Mare Mare :: operator + ( Mare &B ) { // C = A + B
- int i, t = 0; Mare C ;
- for ( i = 1; i <= A[0] || i <= B[0] || t; ++i, t /= base )
- C[i] = ( t += verf ( A, i ) + verf ( B, i ) ) % base ;
- C[0] = i - 1;
- return C ;
- }
- int Mare :: zero ( void ) { // A == 0 ?
- return A[0] == 0 || A[0] == 1 && A[1] == 0 ;
- }
- int Mare :: comparare ( Mare &B ) {
- for ( ; A[0] && !A[A[0]] ; --A[0] ) ;
- for ( ; B[0] && !B[B[0]] ; --B[0] ) ;
- if ( A[0] < B[0] ) return -1;
- else if ( A[0] > B[0] ) return 1;
- for ( int i = A[0]; i > 0; --i )
- if ( A[i] < B[i] ) return -1;
- else if ( A[i] > B[i] ) return 1;
- return 0;
- }
- bool Mare :: operator < ( Mare &B ) { // A < B ?
- return A.comparare ( B ) == -1 ;
- }
- bool Mare :: operator <= ( Mare &B ) { // A <= B ?
- return A.comparare ( B ) != 1 ;
- }
- bool Mare :: operator > ( Mare &B ) { // A > B ?
- return A.comparare ( B ) == 1 ;
- }
- bool Mare :: operator >= ( Mare &B ) {// A >= B ?
- return A.comparare ( B ) != -1 ;
- }
- bool Mare :: operator == ( Mare &B ) {// A == B ?
- return A.comparare ( B ) == 0 ;
- }
- bool Mare :: operator != ( Mare &B ) {// A != B ?
- return A.comparare ( B ) != 0 ;
- }
- void Mare :: operator |= ( Mare &B ) { // A |= B
- int X[MAX * nbase], Y[MAX * nbase] ;
- A.transform_2 ( X ) , B.transform_2 ( Y ) ;
- for ( int i = 1; i <= X[0] && i <= Y[0]; ++i )
- X[i] |= Y[i] ;
- if ( X[0] < Y[0] ) {
- for ( int i = X[0] + 1 ; i <= Y[0] ; ++i )
- X[i] = Y[i] ;
- X[0] = Y[0] ;
- }
- A.transform_210 ( X ) ;
- }
- void Mare :: operator &= ( Mare &B ) { // A &= B
- int X[MAX * nbase], Y[MAX * nbase] ;
- A.transform_2 ( X ) , B.transform_2 ( Y ) ;
- for ( int i = 1; i <= X[0] && i <= Y[0]; ++i )
- X[i] &= Y[i] ;
- X[0] = min ( X[0], Y[0] ) ;
- A.transform_210 ( X ) ;
- }
- void Mare :: operator ^= ( Mare &B ) { // A ^= B
- int X[MAX * nbase], Y[MAX * nbase] ;
- A.transform_2 ( X ) , B.transform_2 ( Y ) ;
- for ( int i = 1; i <= X[0] && i <= Y[0]; ++i )
- X[i] ^= Y[i] ;
- if ( X[0] < Y[0] ) {
- for ( int i = X[0] + 1 ; i <= Y[0] ; ++i )
- X[i] = Y[i] ;
- X[0] = Y[0] ;
- }
- A.transform_210 ( X ) ;
- }
- void Mare :: radical_cb ( Mare &B ) { // B = sqrt ( A ) ; doar parte intreaga
- Mare cnt, X ;
- for ( cnt = 1; cnt < A; cnt *= 2 ) ;
- for ( B[0] = 1 ; ! cnt.zero () ; cnt /= 2 ) {
- X = cnt, X += B, X *= X ;
- if ( X <= A )
- B += cnt ;
- }
- }
- void Mare :: afis ( void ) { // afisarea
- printf ( "%d", A[ A[0] ] ) ;
- for ( int i = A[0] - 1; i ; --i ) {
- printf ( "%09d", A[i] ) ;
- }
- }
- void Mare :: afis_rad ( int nrzecimale ) { // afisarea radicalului
- int X[MAX * nbase] ;
- A.transform_10 ( X ) ;
- for ( int i = X[0]; i > nrzecimale ; --i )
- printf ( "%d", X[i] ) ;
- printf ( "." ) ;
- for ( int i = nrzecimale ; i ; --i ) {
- printf ( "%d", X[i] ) ;
- }
- }
- void Mare :: obtain ( int x, int *X ) {
- int S[10] = { 0 } ;
- for ( int i = A[x]; i ; i /= 10 )
- S[ ++S[0] ] = i % 10 ;
- for ( int i = 1; i <= S[0] ; ++i )
- X[ ++X[0] ] = S[i] ;
- if ( x != A[0] )
- for ( int i = S[0]; i < nbase; ++i )
- X[ ++X[0] ] = 0 ;
- }
- void Mare :: pow ( int P ) { // A = A^P
- Mare B = 1 ;
- for ( ; P ; P >>= 1 ) {
- if ( P & 1 )
- B *= A ;
- A *= A ;
- }
- A = B ;
- }
- void Mare :: transform_2 ( int *X ) { // baza 'base' -> baza 2
- Mare B = A ;
- X[0] = 0 ;
- for ( ; !B.zero () ; X[ ++X[0] ] = B[ 1 ] & 1, B /= 2 ) ;
- }
- void Mare :: transform_10 ( int *X ) { // baza 'base' -> baza 10
- X[0] = 0 ;
- for ( int i = 1; i <= A[0]; ++i )
- obtain ( i, X ) ;
- }
- void Mare :: transform_210 ( int *X ) { // baza 2 -> baza 'base'
- Mare B = 1 ; A = 0 ;
- for ( int i = 1; i <= X[0]; ++i, B *= 2 ) {
- if ( X[i] == 1 ) A += B ;
- }
- }
- void Mare :: radical_normal ( Mare &B, int nrzecimale ) {
- int AUX = 0, i , j = 0 ; int X[MAX * nbase] ;
- Mare C, D, E, F, U = 9 , Z = 1 ;
- A.transform_10 ( X ), i = X[0] ;
- X[0] & 1 ? AUX = X[i--] : ( AUX = X[i--], AUX *= 10, AUX += X[i--] ) ;
- int aux = static_cast < int > ( sqrt ( AUX ) ) ;
- B = aux ;
- if ( X[0] > 2 ) {
- AUX -= aux * aux;
- E = AUX, E <<= 1, F = X[i--] ;
- if ( AUX ) E += F, E <<= 1 ;
- else E = F ;
- if ( AUX == 0 && X[i + 1] ) E <<= 1 ;
- F = X[i--], E += F, C = E, F = B, F *= 2, E = F ;
- D = C, D >>= 1, D /= E, U < D ? D = 9 : 0 ;
- E <<= 1, E += D, E *= D ;
- while ( C < E )
- D -= Z, F = B, F *= 2, E = F, E <<= 1, E += D, E *= D ;
- C -= E, B <<= 1, B += D ;
- } else {
- C = AUX - ( aux * aux ) ;
- }
- if ( !C.zero () || i > 0 ) {
- for ( i = i; i > 0 || j < nrzecimale ; ) {
- if ( i > 0 ) {
- E = X[i--], F = 0, F <<= 1, F = E, E = X[i--];
- if ( X[i + 2] ) F <<= 1, F += E ;
- else F = E ;
- } else {
- ++j, F = 0 ;
- if ( j == 1 && C.zero () ) {
- for ( int i = 1; i <= nrzecimale ; ++i )
- B <<= 1 ;
- return ;
- }
- }
- if ( !C.zero () || i == 3 + ( X[0] % 2 == 0 ) && AUX ) {
- C <<= 2, C += F ;
- } else {
- C = F ;
- }
- F = B, F *= 2, E = F ;
- D = C, D >>= 1, D /= E, U < D ? D = 9 : 0 ;
- E <<= 1, E += D, E *= D ;
- while ( C < E )
- D -= Z, F = B, F *= 2, E = F, E <<= 1, E += D, E *= D ;
- C -= E, B <<= 1, B += D ;
- }
- } else {
- for ( int i = 1; i <= nrzecimale ; ++i )
- B <<= 1 ;
- }
- }
- # undef A
- int main ( void ) {
- int a, b ;
- fscanf ( fopen ( "adunare.in", "r" ), "%d %d", &a, &b ) ;
- fprintf ( fopen ( "adunare.out", "w" ), "%d\n", a + b ) ;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //evaluare expresii
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- inline int factor() {
- int r=0;
- if(*p=='(') {
- ++p;
- r=eval();
- ++p;
- } else
- while(*p>='0' && *p<='9') {
- r=r*10+*p-'0';
- ++p;
- }
- return r;
- }
- inline int termen() {
- int r=factor();
- while(*p=='*'||*p=='/') {
- if(*(p++)=='*')
- r*=factor();
- else
- r/=factor();
- }
- return r;
- }
- inline int eval() {
- int r=termen();
- while(*p=='+' || *p=='-') {
- if(*(p++) =='+')
- r+=termen();
- else
- r-=termen();
- }
- return r;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //KMP (Laur)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- vector<int> matches;
- string sir, subsir;
- int pi[2000000+10];
- getline(fin, subsir);
- getline(fin, sir );
- subsir.insert(subsir.begin(),'-');//incepem de la 1, nu de la 0 //TODO
- sir.insert(sir.begin(),'-'); //incepem de la 1, nu de la 0 //TODO
- if (sir.size()<subsir.size()) {
- fout<<0<<'\n';
- return 0;
- }
- int k=0;
- pi[1]=0;
- for(int i=2; i<subsir.length(); ++i) { //incepem de la al 2-lea caracter
- while(k>0 && subsir[i] != subsir[k+1])
- k=pi[k];
- if(subsir[i] == subsir[k+1])
- k++;
- pi[i]=k;
- }
- k=0;
- int nr=0;
- for(int i=1; i<sir.length(); ++i) { //de la 1 pana la length-1, deoarece am inserat un caracter '-' inainte
- while(k>0 && sir[i] != subsir[k+1])
- k=pi[k];
- if(sir[i] == subsir[k+1])
- k++;
- if(k==subsir.length()-1) { //match
- matches.push_back(i-subsir.length()+1);
- }
- }
- //////////////////////////////////////////////////////////////
- //KMP (Laur) -- sir ce incepe de la 0
- //////////////////////////////////////////////////////////////
- //sirul de la 0 la n-1, dar pi de la 1 la n
- vector<int> matches;
- string sir, subsir;
- int pi[2000000+10];
- getline(fin, subsir);
- getline(fin, sir );
- // subsir.insert(subsir.begin(),'-');//incepem de la 1, nu de la 0 //TODO
- // sir.insert(sir.begin(),'-'); //incepem de la 1, nu de la 0 //TODO
- if (sir.size()<subsir.size()) {
- fout<<0<<'\n';
- return 0;
- }
- int k=0;
- pi[1]=0;
- for(int i=1; i<subsir.length(); ++i) {
- while(k>0 && subsir[i] != subsir[k])
- k=pi[k];
- if(subsir[i] == subsir[k])
- k++;
- pi[i+1]=k; //!!! important
- }
- k=0;
- int nr=0;
- for(int i=0; i<sir.length(); ++i) {
- while(k>0 && sir[i] != subsir[k])
- k=pi[k];
- if(sir[i] == subsir[k])
- k++;
- if(k==subsir.length()) { //match
- matches.push_back(i-subsir.length()+1);
- }
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //euclid extins
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- inline int euclid(int a, int b, int& x, int& y) {
- if(b==0) {
- x=1;
- y=0;
- return a;
- }
- int x0,y0,D;
- D=euclid(b,a%b,x0,y0);
- x=y0;
- y=x0 - (a/b) * y0;
- return D;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //hashuri
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include<ext/hash_map>
- using namespace __gnu_cxx;
- hash_multimap<int,int> H;
- hash_map<char*,int> H;
- //////////////////////////////////////////
- #include<tr1/unordered_map>
- using namespace tr1;
- unordered_map<string,int> H;//unordered_map merge doar in code blocks, nu in mingw!!
- //////////////////////////////////////////
- #include <vector>
- #include <cmath>
- #include <cstdio>
- #define MOD 666013
- const double CST = (sqrt(5)-1)/(double)2;
- using namespace std;
- int N;
- vector<int> G[MOD];
- inline vector<int>::iterator find_value(int x) {
- int list = x % MOD;
- // double tmp;
- // int list = floor(MOD*(double)modf((double)x*CST,&tmp));
- vector<int>::iterator it;
- for (it = G[list].begin(); it != G[list].end(); ++it)
- if (*it == x)
- return it;
- return G[list].end();
- }
- inline void insert_value(int x) {
- int list = x % MOD;
- // double tmp;
- // int list = floor(MOD*(double)modf((double)x*CST,&tmp));
- if (find_value(x) == G[list].end())
- G[list].push_back(x);
- }
- inline void erase_value(int x) {
- int list = x % MOD;
- // double tmp;
- // int list = floor(MOD*(double)modf((double)x*CST,&tmp));
- vector<int>::iterator it = find_value(x);
- if (it != G[list].end())
- G[list].erase(it);
- }
- int main() {
- int op, x;
- freopen("hashuri.in", "r", stdin);
- freopen("hashuri.out", "w", stdout);
- for (scanf("%d", &N); N; --N) {
- scanf("%d %d", &op, &x);
- if (op == 1) { // inserare
- insert_value(x);
- continue;
- }
- if (op == 2) { // stergere
- erase_value(x);
- continue;
- }
- int list = x % MOD;
- // double tmp;
- // int list = floor(MOD*(double)modf((double)x*CST,&tmp));
- printf("%d\n", find_value(x) != G[list].end());
- }
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- // radix sort
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include<cstring>//pt memset
- int A[MAX_N], N, K, B[MAX_N];
- //#define a_de_i ((A[i]>>byte)&255)
- inline void rad(int N, int byte, int A[], int B[]) {
- int cnt[256], ind[256],i;
- memset(cnt, 0, sizeof(cnt));
- for(i=1; i <= N; ++i) ++cnt[(A[i]>>byte)&255];
- ind[0]=1;
- for(i=1; i < 256; ++i) ind[i]=ind[i-1]+cnt[i-1];
- for(i=1; i <= N; ++i) B[ind[(A[i]>>byte)&255]++]=A[i];
- }
- inline void radix(int A[], int N) {
- rad(N, 0, A, B);//sortez dupa primii 8 biti (1-8)
- rad(N, 8, B, A);//urmatorii 8 biti (9-16)
- rad(N, 16, A, B);//urmatorii 8 biti (17-24)
- rad(N, 24, B, A);//urmatorii 8 biti (25-32)
- }
- int main() {
- fin >> N >> K;
- for(int i = 1; i <= N; ++i)
- fin >> A[i];
- radix(A, N);
- fout << A[K] << "\n";
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //treapuri (by me) - not tested!
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- struct treapNode {
- int val, priority;
- //int din;//nr de noduri din subarborii nodului x
- treapNode *left, *right;
- }*r, *nil;
- void rotright(treapNode*& x) {
- treapNode* tmp=x->left;
- x->left=tmp->right,tmp->right=x;
- //x->din=x->left->din+x->right->din+1;
- //tmp->din=tmp->left->din+tmp->right->din+1;
- x = tmp;
- }
- void rotleft(treapNode*& x) {
- treapNode* tmp=x->right;
- x->right=tmp->left,tmp->left=x;
- //x->din=x->left->din+x->right->din+1;
- //tmp->din=tmp->left->din+tmp->right->din+1;
- x = tmp;
- }
- void balance(treapNode*& x) {
- if(x->left->priority>x->priority)
- rotright(x);
- else if(x->right->priority<x->priority)
- rotleft(x);
- //x->din=x->left->din+x->right->din+1;
- }
- void insert(treapNode*& x,int& val, int& priority) {
- if(x==nil) {
- x=new treapNode();
- x->val=val;
- x->priority=priority;
- x->left=x->right=nil;
- //x->din=1;
- return;
- }
- if(x->val<val)
- insert(x->left, val, priority);
- else
- insert(x->right, val, priority);
- balance(x);
- }
- void erase(treapNode*& x, int& val) {
- if(x==nil)
- return;
- if(x->val==val) {
- if(x->left==nil && x->right==nil)
- delete x,x=nil;
- else {
- if(x->left->priority<x->priority)
- rotright(x);
- else if(x->right->priority>x->priority)
- rotleft(x);
- erase(x, val);
- }
- } else if(x->val<val)
- erase(x->left,val);
- else
- erase(x->right, val);
- }
- /*
- void query(treapNode *t)
- {
- if(k==t->left->din+1)
- {
- printf("%d\n",t->key);
- return;
- }
- if(k>t->left->din)
- {
- k=k-t->left->din-1;
- query(t->right);
- }
- else
- query(t->left);
- }
- */
- treapNode* find(treapNode*& x, int& val) {
- if(x->val==val)
- return x;
- if(x->val<val)
- return find(x->left, val);
- else
- return find(x->right, val);
- }
- int main() {
- nil=new treapNode();
- nil->val=0;
- nil->priority=0;
- nil->left=NULL;
- nil->right=NULL;
- //nil->din=0;
- r=nil;
- srand(time(0));
- /*
- freopen("treapuri.in","r",stdin);
- freopen("treapuri.out","w",stdout);
- scanf("%d",&m);
- int i,tip,val;
- for(i=1;i<=m;i++)
- {
- scanf("%d %d",&tip,&val);
- if(tip==1)
- r=insert(r,val,rand()+1);
- if(tip==2)
- {
- k=val;
- query(r);
- }
- if(tip==3)
- erase(r,val);
- }
- */
- return 0;
- }//treapuri (by me)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //parsarea citirii
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #ifdef _PARSARE_
- #define DIM 8192
- char buff[DIM+16];
- int idx;
- //numere NATURALE:
- inline void cit_uint(int &x) {
- x=0;
- while(buff[idx]<'0' || buff[idx]>'9')
- if(++idx==DIM)fread(buff, 1, DIM, stdin), idx=0;
- while(buff[idx]>='0' && buff[idx]<='9') {
- x=x*10+buff[idx]-'0';
- if(++idx==DIM)fread(buff,1, DIM, stdin),idx=0;
- }
- }
- //numere INTREGI:
- inline void cit_int(int &x) {
- x=0;
- while((buff[idx]<'0' || buff[idx]>'9') && (buff[idx]!='-'))
- if(++idx==DIM)fread(buff, 1, DIM, stdin), idx=0;
- int neg=0;
- if(buff[idx]=='-') {
- neg=1;
- if(++idx==DIM)fread(buff, 1, DIM, stdin),idx=0;
- }
- while(buff[idx]>='0' && buff[idx]<='9') {
- x=x*10+buff[idx]-'0';
- if(++idx==DIM)fread(buff,1, DIM, stdin),idx=0;
- }
- if(neg) x=-x;
- }
- #endif //_PARSARE_
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //subsecventa de suma maxima
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////VARIANTA MEA (BOSS)://////////
- //daca avem cel putin un nr pozitiv:
- int best=0,maxSum=-0x3f3f3f3f;
- for(int i=0; i<n; ++i) {
- scanf("%d ",&x);
- if(best>0)
- best=x+best;
- else
- best=x,i1=i;
- if(maxSum<best)
- maxSum=best,begin=i1+1,end=i+1;
- }
- printf("%d %d %d\n",maxSum,begin,end);
- //cu vectori (inutili): (scop didactic)
- bestSum = a[1];
- for (i = 1; i <= N; ++ i) {
- best[i] = a[i];
- if (best[i] < best[i-1] + a[i])
- best[i] = best[i-1] + a[i];
- if (bestSum < best[i])
- bestSum = best[i];
- }
- //formula de recurenta: best[i] = max(a[i], best[i-1] + a[i])
- //fara vectori (care erau inutili)
- bestSum=a[0];
- for(int i=0; i<n; ++i) {
- best=a[i];
- if(best<bestOld+a[i])
- best=bestOld+a[i];
- if(bestSum<best)
- bestSum=best;
- }
- //cu sume partiale, mai slow (cred)
- sum[0] = 0;
- for (i = 1; i <= N; i++) sum[i] = a[i] + sum[i-1];
- min = sum[0];
- bestSum = -INF;
- for (i = 1; i <= N; i++) {
- best[i] = sum[i] - min;
- if (min > sum[i]) min = sum[i];
- if (bestSum < best[i]) bestSum = best[i];
- }
- //daca avem cel putin un nr pozitiv: // not tested!
- sum = 0, bestSum = -INF;
- for (i = 1; i <= N; i++) {
- sum += a[i];
- if (sum < 0)
- sum = 0;
- else if (sum > bestSum)
- bestSum = sum;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //AVL-uri (Radu Berinde)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #define max(a, b) ((a) > (b) ? (a) : (b))
- #define geth(n) (n->h = 1 + max(n->l->h, n->r->h))
- struct AVLnode {
- int key, h;
- struct AVLnode *l, *r;
- } *R, *NIL;
- typedef struct AVLnode AVLnode;
- void init(void) {
- R = NIL = (AVLnode *) malloc(sizeof(AVLnode));
- NIL->key = NIL->h = 0,
- NIL->l = NIL->r = NULL;
- }
- AVLnode* rotleft(AVLnode *n) {
- AVLnode *t = n->l;
- n->l = t->r, t->r = n,
- geth(n), geth(t);
- return t;
- }
- AVLnode* rotright(AVLnode *n) {
- AVLnode *t = n->r;
- n->r = t->l, t->l = n,
- geth(n), geth(t);
- return t;
- }
- AVLnode* balance(AVLnode *n) {
- geth(n);
- if (n->l->h > n->r->h + 1) {
- if (n->l->r->h > n->l->l->h)
- n->l = rotright(n->l);
- n = rotleft(n);
- } else if (n->r->h > n->l->h + 1) {
- if (n->r->l->h > n->r->r->h)
- n->r = rotleft(n->r);
- n = rotright(n);
- }
- return n;
- }
- AVLnode* insert(AVLnode *n, int key) {
- if (n == NIL) {
- n = (AVLnode *) malloc(sizeof(AVLnode));
- n->key = key, n->h = 1, n->l = n->r = NIL;
- return n;
- }
- if (key < n->key)
- n->l = insert(n->l, key);
- else
- n->r = insert(n->r, key);
- return balance(n);
- }
- AVLnode* erase(AVLnode *n, int key) {
- AVLnode *t;
- if (n == NIL) return n;
- if (n->key == key) {
- if (n->l == NIL || n->r == NIL) {
- t = n->l == NIL ? n->r : n->l;
- free(n);
- return t;
- } else {
- for (t = n->r; t->l != NIL; t = t->l);
- n->key = t->key,
- n->r = erase(n->r, t->key);
- return balance(n);
- }
- }
- if (key < n->key)
- n->l = erase(n->l, key);
- else
- n->r = erase(n->r, key);
- return balance(n);
- }
- int search(AVLnode *n, int key) {
- if (n == NIL) return 0;
- if (n->key == key) return 1;
- if (key < n->key)
- return search(n->l, key);
- else
- return search(n->r, key);
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //Ciurul lui Eratostene
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //bool ciur[maxsize];
- bitset<maxsize> ciur;
- void sieve() {
- long long i, j;
- //memset(ciur,0,sizeof(ciur));
- for (i = 4; i <= maxsize; i += 2)
- ciur[i] = 1;
- for (i = 3; i <= maxsize; i += 2)
- if (!ciur[i]) {
- //daca vreau sa retin toate nr prime intr-un vector:
- //prime[++k]=i;
- for (j = i * i; j <= maxsize; j += i + i)
- ciur[j] = 1;
- }
- }
- //////////////////////////////////////////
- //varianta cu spatiu optim (de 16 ori mai mic): //NETESTAT!
- //////////////////////////////////////////
- #define maxsize 10000000
- char at[maxsize / 16];
- int n;
- int isPrime(int x) {
- if (!(x & 1))
- if (x == 2) return 0 ;
- else return 1 ;
- else return (at[((x - 3) >> 1) >> 8] & (1 << (((x - 3) >> 1) & 7))) ;
- }
- void sieve() {
- int i, j;
- memset(at, 0, sizeof(at)) ;
- for (i = 3; i <= maxsize; i += 2)
- if (!at[((i - 3) >> 1) >> 8] & (1 << (((i - 3) >> 1) & 7)))
- for (j = i * i ; j <= maxsize ; j += i + i)
- at[((i - 3) >> 1) >> 8] |= (1 << (((i - 3) >> 1) & 7))) ;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- diverse clase si templateuri:
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <set>
- #include <bitset>
- #include <queue>
- #include <deque>
- #include <stack>
- #include <sstream>
- #include <iostream>
- #include <iomanip>
- #include <cstdio>
- #include <cstdlib>
- #include <cmath>
- #include <ctime>
- #include <cstring>
- #include <string>
- #include <cassert>
- #include <vector>
- #include <list>
- #include <map>
- #include <algorithm>
- #include <functional>
- #include <numeric>
- #include <utility>
- using namespace std;
- typedef vector<int> vi;
- typedef vector<vi> vvi;
- typedef pair<int, int> ii;
- typedef long long int64; //NOTES:int64
- typedef unsigned long long uint64; //NOTES:uint64
- const double pi = acos(-1.0); //NOTES:pi
- const double eps = 1e-11; //NOTES:eps
- const int MAXI = 2 << 29;
- #define FORN(i,a,b) for (int i=(a),_b=(b); i<_b; i++)
- #define RFORN(i,b,a) for (int i=(b)-1,_a=(a); i>=_a; i--)
- #define RESET(a,b) memset((a),(b),sizeof(a))
- #define SC(x) scanf("%d",&x)
- #define SC2(x,y) scanf("%d%d",&x,&y)
- #define PR(x) printf("%d ",x)
- #define PR2(x,y) printf("%d %d ",x,y)
- #define PRS(x) printf("%s",x)
- #define END printf("\n")
- #define EXIT(x) {PRS(x);return 0;}
- #define DBG(x) {cerr << "--> " << #x << " = " << x << endl;}
- #define fi first
- #define se second
- #define PB push_back
- #define ALL(x) (x).begin(),(x).end()
- #define MP(X,Y) make_pair(X,Y)//NOTES:MP(
- #define TR(c, i) for(typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
- #define present(c, x) ((c).find(x) != (c).end())
- int compare (const void *a, const void *b) {
- return (*(int*)a-*(int*)b);
- }
- void startDBG() {
- PRS("------------------- Start Debug -------------------\n\n");
- }
- void endDBG() {
- PRS("\n\n------------------- End Debug -------------------\n");
- }
- template<class T> inline void DebM(T A[], T ii, T jj) { //Debug sequence
- END;
- PRS("----------------DEBUG----------------");
- END;
- FORN (i,ii,jj) cout<<A[i]<<" ";
- END;
- PRS("-------------------------------------");
- END;
- }
- //Template code by ACRush
- template<class T> inline bool isPrimeNumber(T n) { //NOTES:isPrimeNumber(
- if (n <= 1)return false;
- for (T i = 2; i * i <= n; i++) if (n % i == 0) return false;
- return true;
- }
- template<class T> inline void checkmin(T &a, T b) {
- if (b < a) a = b;
- }//NOTES:checkmin(
- template<class T> inline void checkmax(T &a, T b) {
- if (b > a) a = b;
- }//NOTES:checkmax(
- template<class T> inline T sqr(T x) {
- return x*x;
- }//NOTES:sqr
- template<class T> inline T lowbit(T n) {
- return (n^(n - 1))&n;
- }//NOTES:lowbit(
- template<class T> inline int countbit(T n) {
- return (n == 0) ? 0 : (1 + countbit(n & (n - 1)));
- }//NOTES:countbit(
- //Numberic Functions
- template<class T> inline T gcd(T a, T b) { //NOTES:gcd(
- if (a < 0)return gcd(-a, b);
- if (b < 0)return gcd(a, -b);
- return (b == 0) ? a : gcd(b, a % b);
- }
- template<class T> inline T lcm(T a, T b) { //NOTES:lcm(
- if (a < 0)return lcm(-a, b);
- if (b < 0)return lcm(a, -b);
- return a * (b / gcd(a, b));
- }
- template<class T> inline T euclide(T a, T b, T &x, T &y) { //NOTES:euclide(
- if (a < 0) {
- T d = euclide(-a, b, x, y);
- x = -x;
- return d;
- }
- if (b < 0) {
- T d = euclide(a, -b, x, y);
- y = -y;
- return d;
- }
- if (b == 0) {
- x = 1;
- y = 0;
- return a;
- } else {
- T d = euclide(b, a % b, x, y);
- T t = x;
- x = y;
- y = t - (a / b) * y;
- return d;
- }
- }
- template<class T> inline vector<pair<T, int> > factorize(T n) { //NOTES:factorize(
- vector<pair<T, int> > R;
- for (T i = 2; n > 1;) {
- if (n % i == 0) {
- int C = 0;
- for (; n % i == 0; C++, n /= i);
- R.push_back(make_pair(i, C));
- }
- i++;
- if (i > n / i) i = n;
- }
- if (n > 1) R.push_back(make_pair(n, 1));
- return R;
- }
- template<class T> inline T eularFunction(T n) { //NOTES:eularFunction(
- vector<pair<T, int> > R = factorize(n);
- T r = n;
- for (int i = 0; i < R.size(); i++)r = r / R[i].first * (R[i].first - 1);
- return r;
- }
- //Matrix Operations
- const int MaxMatrixSize = 40; //NOTES:MaxMatrixSize
- template<class T> inline void showMatrix(int n, T A[MaxMatrixSize][MaxMatrixSize]) { //NOTES:showMatrix(
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < n; j++)cout << A[i][j];
- cout << endl;
- }
- }
- template<class T> inline T checkMod(T n, T m) {
- return (n % m + m) % m;
- }//NOTES:checkMod(
- template<class T> inline void identityMatrix(int n, T A[MaxMatrixSize][MaxMatrixSize]) { //NOTES:identityMatrix(
- for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) A[i][j] = (i == j) ? 1 : 0;
- }
- template<class T> inline void addMatrix(int n, T C[MaxMatrixSize][MaxMatrixSize], T A[MaxMatrixSize][MaxMatrixSize], T B[MaxMatrixSize][MaxMatrixSize]) { //NOTES:addMatrix(
- for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) C[i][j] = A[i][j] + B[i][j];
- }
- template<class T> inline void subMatrix(int n, T C[MaxMatrixSize][MaxMatrixSize], T A[MaxMatrixSize][MaxMatrixSize], T B[MaxMatrixSize][MaxMatrixSize]) { //NOTES:subMatrix(
- for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) C[i][j] = A[i][j] - B[i][j];
- }
- template<class T> inline void mulMatrix(int n, T C[MaxMatrixSize][MaxMatrixSize], T _A[MaxMatrixSize][MaxMatrixSize], T _B[MaxMatrixSize][MaxMatrixSize]) { //NOTES:mulMatrix(
- T A[MaxMatrixSize][MaxMatrixSize], B[MaxMatrixSize][MaxMatrixSize];
- for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) A[i][j] = _A[i][j], B[i][j] = _B[i][j], C[i][j] = 0;
- for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) for (int k = 0; k < n; k++) C[i][j] += A[i][k] * B[k][j];
- }
- template<class T> inline void addModMatrix(int n, T m, T C[MaxMatrixSize][MaxMatrixSize], T A[MaxMatrixSize][MaxMatrixSize], T B[MaxMatrixSize][MaxMatrixSize]) { //NOTES:addModMatrix(
- for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) C[i][j] = checkMod(A[i][j] + B[i][j], m);
- }
- template<class T> inline void subModMatrix(int n, T m, T C[MaxMatrixSize][MaxMatrixSize], T A[MaxMatrixSize][MaxMatrixSize], T B[MaxMatrixSize][MaxMatrixSize]) { //NOTES:subModMatrix(
- for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) C[i][j] = checkMod(A[i][j] - B[i][j], m);
- }
- template<class T> inline T multiplyMod(T a, T b, T m) {
- return (T) ((((int64) (a)*(int64) (b) % (int64) (m))+(int64) (m)) % (int64) (m));
- }//NOTES:multiplyMod(
- template<class T> inline void mulModMatrix(int n, T m, T C[MaxMatrixSize][MaxMatrixSize], T _A[MaxMatrixSize][MaxMatrixSize], T _B[MaxMatrixSize][MaxMatrixSize]) { //NOTES:mulModMatrix(
- T A[MaxMatrixSize][MaxMatrixSize], B[MaxMatrixSize][MaxMatrixSize];
- for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) A[i][j] = _A[i][j], B[i][j] = _B[i][j], C[i][j] = 0;
- for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) for (int k = 0; k < n; k++) C[i][j] = (C[i][j] + multiplyMod(A[i][k], B[k][j], m)) % m;
- }
- template<class T> inline T powerMod(T p, int e, T m) { //NOTES:powerMod(
- if (e == 0)return 1 % m;
- else if (e % 2 == 0) {
- T t = powerMod(p, e / 2, m);
- return multiplyMod(t, t, m);
- } else return multiplyMod(powerMod(p, e - 1, m), p, m);
- }
- //Point&Line
- double dist(double x1, double y1, double x2, double y2) {
- return sqrt(sqr(x1 - x2) + sqr(y1 - y2));
- }//NOTES:dist(
- double distR(double x1, double y1, double x2, double y2) {
- return sqr(x1 - x2) + sqr(y1 - y2);
- }//NOTES:distR(
- template<class T> T cross(T x0, T y0, T x1, T y1, T x2, T y2) {
- return (x1 - x0)*(y2 - y0)-(x2 - x0)*(y1 - y0);
- }//NOTES:cross(
- int crossOper(double x0, double y0, double x1, double y1, double x2, double y2) { //NOTES:crossOper(
- double t = (x1 - x0)*(y2 - y0)-(x2 - x0)*(y1 - y0);
- if (fabs(t) <= eps) return 0;
- return (t < 0) ? -1 : 1;
- }
- bool isIntersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { //NOTES:isIntersect(
- return crossOper(x1, y1, x2, y2, x3, y3) * crossOper(x1, y1, x2, y2, x4, y4) < 0 && crossOper(x3, y3, x4, y4, x1, y1) * crossOper(x3, y3, x4, y4, x2, y2) < 0;
- }
- bool isMiddle(double s, double m, double t) {
- return fabs(s - m) <= eps | fabs(t - m) <= eps | (s < m) != (t < m);
- }//NOTES:isMiddle(
- //Translator
- bool isUpperCase(char c) {
- return c >= 'A' && c <= 'Z';
- }//NOTES:isUpperCase(
- bool isLowerCase(char c) {
- return c >= 'a' && c <= 'z';
- }//NOTES:isLowerCase(
- bool isLetter(char c) {
- return c >= 'A' && c <= 'Z' | c >= 'a' && c <= 'z';
- }//NOTES:isLetter(
- bool isDigit(char c) {
- return c >= '0' && c <= '9';
- }//NOTES:isDigit(
- char toLowerCase(char c) {
- return (isUpperCase(c)) ? (c + 32) : c;
- }//NOTES:toLowerCase(
- char toUpperCase(char c) {
- return (isLowerCase(c)) ? (c - 32) : c;
- }//NOTES:toUpperCase(
- template<class T> string toString(T n) {
- ostringstream ost;
- ost << n;
- ost.flush();
- return ost.str();
- }//NOTES:toString(
- int toInt(string s) {
- int r = 0;
- istringstream sin(s);
- sin >> r;
- return r;
- }//NOTES:toInt(
- int64 toInt64(string s) {
- int64 r = 0;
- istringstream sin(s);
- sin >> r;
- return r;
- }//NOTES:toInt64(
- double toDouble(string s) {
- double r = 0;
- istringstream sin(s);
- sin >> r;
- return r;
- }//NOTES:toDouble(
- template<class T> void stoa(string s, int &n, T A[]) {
- n = 0;
- istringstream sin(s);
- for (T v; sin >> v; A[n++] = v);
- }//NOTES:stoa(
- template<class T> void atos(int n, T A[], string &s) {
- ostringstream sout;
- for (int i = 0; i < n; i++) {
- if (i > 0)sout << ' ';
- sout << A[i];
- }
- s = sout.str();
- }//NOTES:atos(
- template<class T> void atov(int n, T A[], vector<T> &vi) {
- vi.clear();
- for (int i = 0; i < n; i++) vi.push_back(A[i]);
- }//NOTES:atov(
- template<class T> void vtoa(vector<T> vi, int &n, T A[]) {
- n = vi.size();
- for (int i = 0; i < n; i++)A[i] = vi[i];
- }//NOTES:vtoa(
- template<class T> void stov(string s, vector<T> &vi) {
- vi.clear();
- istringstream sin(s);
- for (T v; sin >> v; vi.push_bakc(v));
- }//NOTES:stov(
- template<class T> void vtos(vector<T> vi, string &s) {
- ostringstream sout;
- for (int i = 0; i < vi.size(); i++) {
- if (i > 0)sout << ' ';
- sout << vi[i];
- }
- s = sout.str();
- }//NOTES:vtos(
- //Fraction
- template<class T> struct Fraction {
- T a, b;
- Fraction(T a = 0, T b = 1);
- string toString();
- }; //NOTES:Fraction
- template<class T> Fraction<T>::Fraction(T a, T b) {
- T d = gcd(a, b);
- a /= d;
- b /= d;
- if (b < 0) a = -a, b = -b;
- this->a = a;
- this->b = b;
- }
- template<class T> string Fraction<T>::toString() {
- ostringstream sout;
- sout << a << "/" << b;
- return sout.str();
- }
- template<class T> Fraction<T> operator+(Fraction<T> p, Fraction<T> q) {
- return Fraction<T > (p.a * q.b + q.a * p.b, p.b * q.b);
- }
- template<class T> Fraction<T> operator-(Fraction<T> p, Fraction<T> q) {
- return Fraction<T > (p.a * q.b - q.a * p.b, p.b * q.b);
- }
- template<class T> Fraction<T> operator*(Fraction<T> p, Fraction<T> q) {
- return Fraction<T > (p.a * q.a, p.b * q.b);
- }
- template<class T> Fraction<T> operator/(Fraction<T> p, Fraction<T> q) {
- return Fraction<T > (p.a * q.b, p.b * q.a);
- }
- //Template code by ACRush
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- alte define-uri si chestii:
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- /** Repeat **/
- #define REP(I, N) for (int I=0;I<int(N);++I)
- #define FOR(I, A, B) for (int I=int(A);I<int(B);++I)
- #define DWN(I, B, A) for (int I=int(B-1);I>=int(A);--I)
- #define REP_1(I, N) for (int I=1;I<=int(N);++I)
- #define FOR_1(I, A, B) for (int I=int(A);I<=int(B);++I)
- #define DWN_1(I, B, A) for (int I=int(B);I>=int(A);--I)
- #define REP_C(I, N) for (int N____=int(N),I=0;I<N____;++I)
- #define FOR_C(I, A, B) for (int B____=int(B),I=A;I<B____;++I)
- #define DWN_C(I, B, A) for (int A____=int(A),I=B-1;I>=A____;--I)
- #define REP_1_C(I, N) for (int N____=int(N),I=1;I<=N____;++I)
- #define FOR_1_C(I, A, B) for (int B____=int(B),I=A;I<=B____;++I)
- #define DWN_1_C(I, B, A) for (int A____=int(A),I=B;I>=A____;--I)
- #define DO(N) while(N--)
- #define DO_C(N) int N____ = N; while(N____--)
- #define TO(i, a, b) int s_=a<b?1:-1,b_=b+s_;for(int i=a;i!=b_;i+=s_)
- #define TO_1(i, a, b) int s_=a<b?1:-1,b_=b;for(int i=a;i!=b_;i+=s_)
- #define SQZ(I, J, A, B) for (int I=int(A),J=int(B)-1;I<J;++I,--J)
- #define SQZ_1(I, J, A, B) for (int I=int(A),J=int(B);I<=J;++I,--J)
- /** Micro Mezzo Macro Flation -- Overheated Economy **/
- #define ALL(A) A.begin(), A.end()
- #define CPY(A, B) memcpy(A, B, sizeof(A))
- #define INS(A, P, B) A.insert(A.begin() + P, B)
- #define ERS(A, P) A.erase(A.begin() + P)
- #define SRT(A) sort(ALL(A))
- #define BSC(A, X) find(ALL(A), X) // != A.end()
- #define SZ(A) int(A.size())
- #define PB push_back
- #define MP(A, B) make_pair(A, B)
- #define Rush int T____; RD(T____); DO(T____)
- // the size of the stack is set to be ~36 MB
- #pragma comment(linker, "/STACK:36777216")
- #define Ruby system("ruby main.rb")
- #define Haskell system("runghc main.hs")
- #define Pascal system("fpc main.pas")
- /** Typedef **/
- typedef long long LL;
- typedef double DB;
- typedef vector<int> VI;
- typedef vector<string> VS;
- typedef vector<LL> VL;
- typedef vector<DB> VD;
- typedef set<int> SI;
- typedef set<string> SS;
- typedef set<LL> SL;
- typedef set<DB> SD;
- typedef map<int, int> MI;
- typedef map<string, int> MS;
- typedef map<LL, int> ML;
- typedef map<DB, int> MD;
- typedef pair<int, int> PII;
- typedef pair<int, bool> PIB;
- typedef vector<PII> VII;
- typedef set<PII> SII;
- typedef map<PII, int> MII;
- typedef vector<VI> VVI;
- typedef vector<VII> VVII;
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- dijkstra cu heapuri
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <cstdio>
- const int maxn = 50001;
- const int inf = 1 << 30;
- FILE *in = fopen("dijkstra.in","r"), *out = fopen("dijkstra.out","w");
- struct graf {
- int nod, cost;
- graf *next;
- };
- int n, m;
- graf *a[maxn];
- int d[maxn], h[maxn], poz[maxn], k;
- void add(int where, int what, int cost) {
- graf *q = new graf;
- q->nod = what;
- q->cost = cost;
- q->next = a[where];
- a[where] = q;
- }
- void read() {
- fscanf(in, "%d %d", &n, &m);
- int x, y, z;
- for ( int i = 1; i <= m; ++i ) {
- fscanf(in, "%d %d %d", &x, &y, &z);
- add(x, y, z);
- }
- }
- void swap(int x, int y) {
- int t = h[x];
- h[x] = h[y];
- h[y] = t;
- }
- void upheap(int what) {
- int tata;
- while ( what > 1 ) {
- tata = what >> 1;
- if ( d[ h[tata] ] > d[ h[what] ] ) {
- poz[ h[what] ] = tata;
- poz[ h[tata] ] = what;
- swap(tata, what);
- what = tata;
- } else
- what = 1;
- }
- }
- void downheap(int what) {
- int ui;
- while ( what <= k ) {
- ui = what;
- if ( (what<<1) <= k ) {
- ui = what << 1;
- if ( ui + 1 <= k )
- if ( d[ h[ui + 1] ] < d[ h[ui] ] )
- ++ui;
- } else
- return;
- if ( d[ h[what] ] > d[ h[ui] ] ) {
- poz[ h[what] ] = ui;
- poz[ h[ui] ] = what;
- swap(what, ui);
- what = ui;
- } else
- return;
- }
- }
- void dijkstra_heap() {
- for ( int i = 2; i <= n; ++i )
- d[i] = inf, poz[i] = -1;
- poz[1] = 1;
- h[++k] = 1;
- while ( k ) {
- int min = h[1];
- swap(1, k);
- poz[ h[1] ] = 1;
- --k;
- downheap(1);
- graf *q = a[min];
- while ( q ) {
- if ( d[q->nod] > d[min] + q->cost ) {
- d[q->nod] = d[min] + q->cost;
- if ( poz[q->nod] != -1 )
- upheap( poz[q->nod] );
- else {
- h[++k] = q->nod;
- poz[ h[k] ] = k;
- upheap( k );
- }
- }
- q = q->next;
- }
- }
- }
- int main() {
- read();
- dijkstra_heap();
- for ( int i = 2; i <= n; ++i )
- fprintf(out, "%d ", d[i] == inf ? 0 : d[i]);
- fprintf(out, "\n");
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- dijkstra cu set
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- inline void dijkstra() {
- memset(d,0x3f,sizeof(d));
- set<pair<int,int> > S;
- d[1]=0;
- S.insert(make_pair(0,1));
- while(!S.empty()) {
- int nod=S.begin()->second,cost=S.begin()->first;
- S.erase(S.begin());
- for(vector<muchie>::iterator it=G[nod].begin(),stop=G[nod].end(); it<stop; ++it) {
- if( d[it->vec] > cost + it->cost ) {
- //S.insert( make_pair( d[it->vec], it->vec ) );//teoretic mai repede, practic nu
- d[it->vec] = cost + it->cost;
- S.insert( make_pair( d[it->vec], it->vec ) );
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- dijkstra cu priority_queue
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //dijkstra cu priority_queue
- #include<cstdio>
- #include<iostream>
- #include<fstream>
- #include<algorithm>
- #include<set>
- #include<queue>
- #include<cstring>
- #include<vector>
- using namespace std;
- ifstream fin("dijkstra.in");
- ofstream fout("dijkstra.out");
- struct muchie {
- int vec,cost;
- };
- vector <muchie> G[50000+10];
- int viz[50000+10],d[50000+10];
- bool cmp(const pair<int,int> &a, const pair<int,int> &b)
- {
- if(a.first == b.first)
- return a.second<b.second;
- return a.first<b.first;
- }
- inline void dijkstra()
- {
- memset(d,0x3f,sizeof(d));
- priority_queue < pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > Q;
- d[1]=0;
- Q.push(make_pair(0,1));
- while(!Q.empty()) {
- int nod=Q.top().second,cost=Q.top().first;
- Q.pop();
- for(vector<muchie>::iterator it=G[nod].begin(),stop=G[nod].end(); it<stop; ++it) {
- if( d[it->vec] > cost + it->cost ) {
- d[it->vec] = cost + it->cost;
- Q.push( make_pair( d[it->vec], it->vec ) );
- }
- }
- }
- }
- int main()
- {
- int n,m;
- fin>>n>>m;
- for(int i=1; i<=m; ++i) {
- int from,to,cost;
- fin>>from>>to>>cost;
- G[from].push_back((muchie) {
- to,cost
- });
- }
- dijkstra();
- for(int i=2; i<=n; ++i)
- fout<<((d[i]==0x3f3f3f3f)?0:d[i])<<' ';
- fout<<'\n';
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- dijkstra cu make_heap
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //dijkstra cu make_heap
- #include<cstdio>
- #include<iostream>
- #include<fstream>
- #include<algorithm>
- #include<set>
- #include<queue>
- #include<cstring>
- #include<vector>
- using namespace std;
- ifstream fin("dijkstra.in");
- ofstream fout("dijkstra.out");
- struct muchie {
- int vec,cost;
- };
- vector <muchie> G[50000+10];
- int viz[50000+10],d[50000+10];
- bool cmp(const pair<int,int> &a, const pair<int,int> &b)
- {
- if(a.first == b.first)
- return a.second<b.second;
- return a.first<b.first;
- }
- inline void dijkstra()
- {
- memset(d,0x3f,sizeof(d));
- // priority_queue < pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > Q;
- vector<pair<int,int> > V;
- d[1]=0;
- V.push_back(make_pair(0,1));
- while(!V.empty()) {
- int nod=V[0].second,cost=V[0].first;
- pop_heap(V.begin(),V.end(),greater<pair<int,int> >());
- V.pop_back();
- for(vector<muchie>::iterator it=G[nod].begin(),stop=G[nod].end(); it<stop; ++it) {
- if( d[it->vec] > cost + it->cost ) {
- d[it->vec] = cost + it->cost;
- V.push_back( make_pair( d[it->vec], it->vec ) );
- push_heap(V.begin(),V.end(),greater<pair<int,int> >());
- }
- }
- }
- }
- int main()
- {
- int n,m;
- fin>>n>>m;
- for(int i=1; i<=m; ++i) {
- int from,to,cost;
- fin>>from>>to>>cost;
- G[from].push_back((muchie) {
- to,cost
- });
- }
- dijkstra();
- for(int i=2; i<=n; ++i)
- fout<<((d[i]==0x3f3f3f3f)?0:d[i])<<' ';
- fout<<'\n';
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Bellman Ford
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- vector<pair<int,int> > G[50000+10];
- queue<int> Q;
- int cnt_in_queue[50000+10];
- bool in_queue[50000+10];
- int d[50000+10];
- inline void bellmanford()
- {
- memset(d,0x3f,sizeof(d));
- d[1]=0;
- Q.push(1);
- in_queue[1]=true;
- cnt_in_queue[1]=1;
- while(!Q.empty()) {
- int nod=Q.front();
- Q.pop();
- in_queue[nod]=false;
- foreach(it,G[nod]) {
- if( d[it->first]>d[nod]+it->second ) {
- d[it->first]=d[nod]+it->second;
- if(!in_queue[it->first]){
- Q.push(it->first);
- in_queue[it->first]=true;
- if(cnt_in_queue[it->first]++>n) {
- fout<<"Ciclu negativ!\n";
- exit(0);
- }
- }
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Johnson -> all pairs shortest paths
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- JOHNSON(G)
- 1 compute G′, where V[G′] = V[G] ∪ {s},
- E[G′] = E[G] ∪ {(s, v) : v ∈ V[G]}, and
- w(s, v) = 0 for all v ∈ V[G]
- 2 if BELLMAN-FORD(G′, w, s) = FALSE
- 3 then print "the input graph contains a negative-weight cycle"
- 4 else for each vertex v ∈ V[G′]
- 5 do set h(v) to the value of δ(s, v)
- computed by the Bellman-Ford algorithm
- 6 for each edge (u, v) ∈ E[G′]
- 7 do
- 8 for each vertex u ∈ V[G]
- 9 do run DIJKSTRA(G, , u) to compute for all v ∈ V[G]
- 10 for each vertex v ∈ V[G]
- 11 do
- 12 return D
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Roy Floyd Warshall
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- scanf("%d",&n);
- for(int i=0; i<n; ++i)
- for(int j=0; j<n; ++j) {
- scanf("%d",&a[i][j]);
- if(a[i][j]==0 && i!=j)
- a[i][j]=0x3f3f3f3f;
- }
- for(int k=0; k<n; ++k)
- for(int i=0; i<n; ++i)
- for(int j=0; j<n; ++j)
- a[i][j]=std::min(a[i][k]+a[k][j],a[i][j]);
- for(int i=0; i<n; ++i,putchar('\n'))
- for(int j=0; j<n; ++j)
- printf("%d ",(a[i][j]==0x3f3f3f3f)?0:a[i][j]);
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- arbori indexati binar
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- void update(int i,int j ,int val) {
- for (int ii=i; ii <= n; ii+=(ii&-ii))
- for(int jj=j; jj<=n; jj+=(jj&-jj))
- aib[ii][jj] = (aib[ii][jj]+ val)%MOD;
- }
- int q(int i,int j) {
- int sum = 0;
- for (int ii=i; ii; ii-=(ii&-ii))
- for(int jj=j; jj; jj-=jj&-jj)
- sum = (sum+aib[ii][jj])%MOD;
- return sum;
- }
- int query(int x1,int y1, int x2, int y2) {
- return q(x2,y2)-q(x1-1,y2)-q(x2,y1-1)+q(x1-1,y1-1);
- }
- /*
- int now=(1+query(a[k].i+1,a[k].i+1,a[k].j-1,a[k].j-1))%MOD;//(1+q(n-a[k].i,a[k].j-1))%MOD;
- s=(s+d[a[k].i][a[k].j])%MOD;
- s=(s+now)%MOD;
- update(a[k].i,a[k].j,now);
- */
- /*
- int now=(1+q(n-a[k].i,a[k].j-1))%MOD;
- s=(s+now)%MOD;
- update(n-a[k].i+1,a[k].j,now);
- */
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- arbori de intervale
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include <fstream>
- #include <assert.h>
- using namespace std;
- #define in "arbint.in"
- #define out "arbint.out"
- #define dim 100001
- int N, M;
- int MaxArb[4*dim+66];
- int start, finish, Val, Pos, maxim;
- inline int Maxim(int a, int b) {
- if ( a > b ) return a;
- return b;
- }
- void Update(int,int,int);
- void Query(int,int,int);
- int main() {
- int X, A, B;
- freopen(in,"r",stdin);
- freopen(out,"w",stdout);
- scanf("%d%d", &N, &M);
- for ( int i = 1; i <= N; i++ ) {
- scanf("%d", &X);
- Pos = i, Val = X;
- Update(1,1,N);
- }
- for ( int i = 1; i <= M; i++ ) {
- scanf("%d%d%d", &X, &A, &B);
- if ( X == 0 ) {
- maxim = -1;
- start = A, finish = B;
- Query(1,1,N);
- printf("%d\n", maxim);
- } else {
- Pos = A, Val = B;
- Update(1,1,N);
- }
- }
- }
- void Update(int nod, int left, int right) {
- if ( left == right ) {
- MaxArb[nod] = Val;
- return;
- }
- int div = (left+right)/2;
- if ( Pos <= div ) Update(2*nod,left,div);
- else Update(2*nod+1,div+1,right);
- MaxArb[nod] = Maxim( MaxArb[2*nod], MaxArb[2*nod+1] );
- }
- void Query(int nod, int left, int right) {
- if ( start <= left && right <= finish ) {
- if ( maxim < MaxArb[nod] ) maxim = MaxArb[nod];
- return;
- }
- int div = (left+right)/2;
- if ( start <= div ) Query(2*nod,left,div);
- if ( div < finish ) Query(2*nod+1,div+1,right);
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Infasuratoare convexa (Convex Hull)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include <algorithm>
- using namespace std;
- #define INF 1000000000
- #define EPS 1e-12
- #define PDD pair<double, double>
- #define x first
- #define y second
- int N, H;
- PDD v[120005], P[120005];
- inline int cmp(double a, double b) {
- if (a + EPS < b) return -1;
- if (b + EPS < a) return +1;
- return 0;
- }
- int cmp_PDD(const PDD &a, const PDD& b) {
- int r = cmp(a.x, b.x);
- if (r != 0) return r == -1;
- return cmp(a.y, b.y) == -1;
- }
- int semn(PDD a, PDD b, PDD c) {
- double A = a.y-b.y, B = b.x-a.x, C = a.x*b.y - b.x*a.y;
- return cmp(A * c.x + B * c.y + C, 0);
- }
- int st[120005], uz[120005];
- void ConvexHull() {
- int i, pas = +1, k;
- sort(v+1, v+N+1, cmp_PDD);
- uz[2] = 1;
- st[1] = 1;
- st[2] = 2;
- k = 2;
- i = 3;
- while (!uz[1]) {
- while (uz[i]) {
- if (i == N)
- pas = -1;
- i += pas;
- }
- while (k >= 2 && semn(v[st[k-1]], v[st[k]], v[i]) == -1)
- uz[st[k--]] = 0;
- st[++k] = i;
- uz[i] = 1;
- }
- H = k-1;
- for (i = 1; i <= H; ++i)
- P[i] = v[st[i]];
- P[H+1] = P[1];
- }
- int main() {
- int i;
- freopen("infasuratoare.in", "r", stdin);
- freopen("infasuratoare.out", "w", stdout);
- scanf("%d", &N);
- for (i = 1; i <= N; ++i)
- scanf("%lf %lf", &v[i].x, &v[i].y);
- ConvexHull();
- printf("%d\n", H);
- for (i = 1; i <= H; ++i)
- printf("%.6lf %.6lf\n", P[i].x, P[i].y);
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //Cele mai apropiate puncte din plan (cmap)
- //distanta minima dintre oricare 2 puncte
- //divide et impera O(n*lgn)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <iostream>
- #include <fstream>
- #include <vector>
- #include <algorithm>
- #include <cassert>
- #include <cmath>
- #include <iomanip>
- using namespace std;
- const char iname[] = "cmap.in";
- const char oname[] = "cmap.out";
- typedef long long i64;
- const int MAX_N = 100005;
- const i64 INF = 4e18;
- vector < pair <i64, i64> > V(MAX_N), X, Y;
- i64 dist(const pair <i64, i64>& a, const pair <i64, i64>& b) {
- return (a.first - b.first) * (a.first - b.first) + (a.second - b.second) * (a.second - b.second);
- }
- i64 go(int st, int dr, vector < pair <i64, i64> >& X, vector < pair <i64, i64> >& Y) {
- if (st >= dr - 1)
- return INF;
- else if (dr - st == 2) {
- if (Y[st] > Y[st + 1])
- swap(Y[st], Y[st + 1]);
- return dist(X[st], X[st + 1]);
- }
- int mid = (st + dr) / 2;
- i64 best = min(go(st, mid, X, Y), go(mid, dr, X, Y));
- merge(Y.begin() + st, Y.begin() + mid, Y.begin() + mid, Y.begin() + dr, V.begin());
- copy(V.begin(), V.begin() + (dr - st), Y.begin() + st);
- int v_size = 0;
- for (int i = st; i < dr; ++ i) if (abs(Y[i].second - X[mid].first) <= best)
- V[v_size ++] = Y[i];
- for (int i = 0; i < v_size - 1; ++ i) {
- for (int j = i + 1; j < v_size && j - i < 8; ++ j)
- best = min(best, dist(V[i], V[j]));
- }
- return best;
- }
- int main(void) {
- int n;
- ifstream in(iname);
- assert(in >> n);
- assert(1 <= n && n <= 100000);
- X.resize(n), Y.resize(n);
- for (int i = 0; i < (int) X.size(); ++ i) {
- assert(in >> X[i].first >> X[i].second);
- assert(-1000000000 <= X[i].first && X[i].first <= +1000000000);
- assert(-1000000000 <= X[i].second && X[i].second <= +1000000000);
- }
- in.close();
- sort(X.begin(), X.end());
- for (int i = 0; i < (int) X.size(); ++ i)
- Y[i] = make_pair(X[i].second, X[i].first);
- ofstream out(oname);
- out << fixed << setprecision(6) << sqrt(go(0, (int) X.size(), X, Y)) << "\n";
- out.close();
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Paduri de multimi disjuncte
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- int root[100000+10];
- int find(int x) {
- int r = x;
- while(root[r]!=r)
- r=root[r];
- //compresia drumurilor
- while(root[x]!=x) {
- int tmp;
- tmp=root[x];
- root[x]=r;
- x=tmp;
- }
- return r;
- }
- void join(int x, int y) {
- //unim radacinile
- x=find(x);
- y=find(y);
- if(rand()%2)
- root[y]=x;
- else
- root[x]=y;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Rabin-Karp (by me)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #define baza 73
- #define mod1 100007
- #define mod2 100021
- vector<int> matches;
- string sir, subsir;
- int hashSir1=0,hashSir2=0,hashSubsir1=0,hashSubsir2=0,baza_n1=1,baza_n2=1;
- getline(fin,subsir);
- getline(fin,sir);
- if (sir.size()<subsir.size()) {
- fout<<0<<'\n';
- return 0;
- }
- for(int i=0; i<subsir.length(); ++i) {
- hashSubsir1 = (hashSubsir1 * baza + subsir[i]) % mod1;
- hashSubsir2 = (hashSubsir2 * baza + subsir[i]) % mod2;
- hashSir1 = (hashSir1 * baza + sir[i] ) % mod1;
- hashSir2 = (hashSir2 * baza + sir[i] ) % mod2;
- if(i>0) {
- baza_n1 = (baza_n1 * baza) % mod1;
- baza_n2 = (baza_n2 * baza) % mod2;
- }
- }
- if(hashSir1 == hashSubsir1 && hashSir2 == hashSubsir2)
- matches.push_back(0);
- for(int i=subsir.length(); i<sir.length(); ++i) {
- hashSir1 = ((hashSir1 - (sir[i - subsir.length()] * baza_n1) % mod1 + mod1) * baza + sir[i]) % mod1;
- hashSir2 = ((hashSir2 - (sir[i - subsir.length()] * baza_n2) % mod2 + mod2) * baza + sir[i]) % mod2;
- if(hashSir1 == hashSubsir1 && hashSir2 == hashSubsir2)
- matches.push_back(i-subsir.length()+1);
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- ciclu eulerian
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <fstream>
- #include <list>
- #include <stack>
- #include <queue>
- using namespace std;
- #define TR( C, it ) \
- for( typeof(C.begin()) it = C.begin(); it != C.end(); it++ )
- #define pb push_back
- #define NX 100010
- list< int > G[ NX ], L;
- stack< int > S;
- queue< int > Q;
- int N, M, deg[ NX ], col[ NX ];
- void cit() {
- int u, v;
- scanf( "%d%d", &N, &M );
- while( M-- ) {
- scanf( "%d%d", &u, &v );
- G[u].pb( v );
- deg[u]++;
- G[v].pb( u );
- deg[v]++;
- }
- }
- void BFS( int v ) {
- Q.push( v );
- col[v] = 1;
- while( !Q.empty() ) {
- v = Q.front();
- Q.pop();
- TR( G[v], w )
- if( col[ *w ] == 0 )
- Q.push( *w ), col[ *w ] = 1;
- }
- }
- int este_conex() {
- BFS( 1 );
- for( int v = 2; v <= N; v++ )
- if( col[ v ] == 0 )
- return 0;
- return 1;
- }
- int eulerian() {
- if( este_conex() == 0 )
- return 0;
- for( int v = 1; v <= N; v++ )
- if( deg[ v ] % 2 == 1 )
- return 0;
- return 1;
- }
- void sterge( int v, int w ) {
- deg[v]--, deg[w]--;
- G[v].pop_front();
- TR( G[w], it )
- if( *it == v ) {
- G[w].erase( it );
- break;
- }
- }
- void euler( int v ) {
- while( true ) {
- if( G[v].empty() )
- break;
- int w = G[v].front();
- S.push( v );
- sterge( v, w );
- v = w;
- }
- }
- int rez() {
- int v = eulerian();
- if( v == 0 )
- return -1;
- do {
- euler( v );
- v = S.top();
- S.pop();
- L.pb( v );
- } while( !S.empty() );
- return 1;
- }
- void scr( int x ) {
- if( x == -1 )
- printf( "-1\n" );
- else {
- TR( L, v )
- printf( "%d ", *v );
- printf( "\n" );
- }
- }
- int main() {
- freopen( "ciclueuler.in", "r", stdin );
- freopen( "ciclueuler.out", "w", stdout );
- cit();
- scr( rez() );
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- ciclu hamiltonian de cost minim (eu)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include<iostream>
- #include<algorithm>
- #include<cstdio>
- #include<vector>
- using namespace std;
- int dp[(1<<19)+10][20],cost[20][20],n,m;
- vector<int> G[20];
- #define INF 0x3f3f3f3f
- int main() {
- freopen("hamilton.in","rt",stdin);
- freopen("hamilton.out","wt",stdout);
- cin>>n>>m;
- for (int i=0; i<n; ++i)
- for (int j=0; j<n; ++j)
- cost[i][j] = INF;
- for (int i=1; i<=m; ++i) {
- int x, y;
- cin>>x>>y;
- G[y].push_back(x);
- cin>>cost[x][y];
- }
- for (int i=0; i< 1<<n; ++i)
- for (int j=0; j<n; ++j)
- dp[i][j] = INF;
- dp[1][0] = 0;
- for(int i=0; i< 1<<n; ++i) {
- for(int j=0; j<n; ++j) {
- if(i&(1<<j)) {
- for(int k=0; k<G[j].size(); ++k) {
- if(i&(1<<G[j][k])) { //daca vecinul lui j este in configuratie (bitul de pe poz lui in configuratia i este 1)
- //cerr<<G[j][k]<<' ';
- dp[i][j]=min(dp[i][j],dp[i^(1<<j)][G[j][k]] + cost[G[j][k]][j]);//
- }
- }
- }
- }
- }
- int minim=INF;
- for(int i=0; i<G[0].size(); ++i) {
- minim=min(minim,dp[(1<<n)-1][G[0][i]]+cost[G[0][i]][0]);
- }
- if(minim==INF)
- cout<<"Nu exista solutie"<<'\n';
- else
- cout<<minim<<'\n';
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- parantezare optima de matrici
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- /*
- Din fericire, principiul optimalităţii al metodei programării dinamice se poate aplica la această problemă. Dacă cel mai bun mod de a înmulţi toate matricele presupune o tăietură între a i-a şi a i + 1 a matrice a produsului, atunci subprodusele M1M2...Mi şi Mi+1Mi+2...Mn trebuie calculate la rândul lor într-un mod optim.
- Vom construi tabloul m[1..n, 1..n], unde m[i, j] este numărul minim de înmulţiri scalare necesare pentru a calcula partea MiMi+1...Mj a produsului iniţial. Soluţia problemei iniţiale va fi m[1, n]. Presupunem că tabloul d[0..n] conţine dimensiunile matricilor, astfel încât matricea Mi este de dimensiuni (d[i-1], d[i]), 1 ≤ i ≤ n. Construcţia tabloului se face diagonală cu diagonală:
- */
- #include <iostream>
- #include <fstream>
- using namespace std;
- const char iname[] = "podm.in";
- const char oname[] = "podm.out";
- #define MAXN 505
- #define Min(a, b) ((a) < (b) ? (a) : (b))
- #define FOR(i, a, b) for (int i = (a); i <= (b); ++ i)
- #define INF 100000000000000000LL
- typedef long long i64;
- i64 bst[MAXN][MAXN], d[MAXN]; int n;
- int main(void)
- {
- ifstream in(iname);
- in >> n;
- FOR (i, 0, n) in >> d[i];
- in.close();
- ofstream out(oname);
- FOR (i, 1, n) bst[i][i] = 0;
- FOR (i, 1, n - 1) bst[i][i + 1] = d[i - 1] * d[i] * d[i + 1];
- FOR (w, 2, n - 1)
- FOR (i, 1, n - w) {
- int j = i + w;
- bst[i][j] = INF;
- FOR (k, i, j - 1)
- bst[i][j] = Min(bst[i][j], bst[i][k] + bst[k + 1][j] + d[i - 1] * d[k] * d[j]);
- }
- out << bst[1][n];
- out.close();
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- dinamica.doc
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Metoda programării dinamice
- Prof. Emanuela Cerchez
- Liceul de Informatica „Grigore Moisil” Iasi
- Prezentare generală
- Programarea dinamică este o metodă de elaborare a algoritmilor care se aplică în general problemelor pentru care se cere determinarea unui optim în urma adoptării unor decizii.
- Nu există un criteriu pe baza căruia să identificăm cu siguranţă o problemă pentru rezolvarea căreia trebuie să utilizăm metoda programării dinamice, dar putem formula două proprietăţi care sugerează o soluţie prin programare dinamică.
- Substructură optimală
- Problema dată poate fi descompusă în subprobleme şi soluţia optimă a problemei depinde de soluţiile optime ale subproblemelor sale.
- Acest criteriu nu indică neapărat o soluţie prin programare dinamică, ar putea fi şi un indiciu că se poate aplica metoda Greedy sau metoda „Divide et Impera”.
- Subprobleme superpozabile
- Subproblemele problemei date nu sunt independente, ci se suprapun.
- Datorită faptului că subproblemele problemei date se suprapun, deducem că o abordare prin metoda „Divide et Impera” ar fi dezastruoasă din punctul de vedere al timpului de execuţie (datorită faptului că problemele se suprapun se ajunge la rezolvarea repetată a aceleiaşi subprobleme). Prin urmare, vom rezolva subproblemele o singură, dată, reţinând rezultatele într-o structură de date suplimentară (de obicei un tablou).
- Rezolvarea unei probleme prin programare dinamică presupune următorii paşi:
- Se identifică subproblemele problemei date.
- Se alege o structură de date suplimentară, capabilă să reţină soluţiile subproblemelor.
- Se caracterizează substructura optimală a problemei printr-o relaţie de recurenţă.
- Pentru a determina soluţia optimă, se rezolvă relaţia de recurenţă în mod bottom-up (se rezolvă subproblemele în ordinea crescătoare a dimensiunii lor).
- În cele ce urmează vom exemplifica pas cu pas modul de rezolvare a problemelor prin metoda programării dinamice.
- 1. Înmulţirea optimală a matricelor
- Fie n matrice A1, A2, ..., An, de dimensiuni d0xd1, d1xd2, ..., dn-1xdn. Produsul A1xA2x...xAn se poate calcula în diverse moduri, aplicând asociativitatea operaţiei de înmulţire a matricelor. Numim înmulţire elementară înmulţirea a două elemente. În funcţie de modul de parantezare diferă numărul de înmulţiri elementare necesare pentru calculul produsului A1xA2x...xAn. Determinaţi o parantezare optimală a produsului A1xA2x...xAn (costul parantezării, adică numărul total de înmulţiri elementare să fie minim).
- Exemplu
- Pentru n=3 matrice cu dimensiunile (10,1000), (1000,10) şi (10,100), produsul A1xA2xA3 se poate calcula în două moduri:
- (A1xA2)xA3 necesitând 1000000+10000=1010000 înmulţiri elementare
- A1x(A2xA3), necesitând 1000000+1000000=2000000 înmulţiri.
- Reamintim că numărul de înmulţiri elementare necesare pentru a înmulţi o matrice A cu n linii şi m coloane şi B o matrice cu m linii şi p coloane este nmp (vezi problema 8 de la capitolul „Structuri elementare de date”).
- Solutie
- Pentru a calcula A1xA2x...xAn, în final trebuie să înmulţim două matrice, deci vom paranteza produsul astfel: (A1xA2x...xAk)x(Ak+1x...xAn ). Această observaţie se aplică şi produselor dintre paranteze. Prin urmare, subproblemele problemei iniţiale constau în determinarea parantezării optimale a produselor de matrice de forma AixAi+1x...xAj, 1ijn. Observăm că subproblemele nu sunt independente. De exemplu, calcularea produsului AixAi+1x...xAj şi calcularea produsului Ai+1xAi+2x...xAj+1, au ca subproblemă comună calcularea produsului Ai+1x...xAj.
- Pentru a reţine soluţiile subproblemelor, vom utiliza o matrice M, cu n linii şi n coloane, cu semnificaţia:
- M[i][j] = numărul minim de înmulţiri elementare necesare pentru a calcula
- produsul AixAi+1x...xAj, 1ijn.
- Evident, numărul minim de înmulţiri necesare pentru a calcula A1xA2x...xAn este M[1][n].
- Pentru ca parantezarea să fie optimală, parantezarea produselor A1xA2x...xAk şi Ak+1x...xAn trebuie să fie de asemenea optimală. Prin urmare elementele matricei M trebuie să satisfacă următoarea relaţie de recurenţă:
- M[i][i]=0, i{1,2,..., n}.
- M[i][j]=min{M[i][k] + M[k+1][j] + d[i-1]*d[k]*d[j]}
- ik<j
- Cum interpretăm această relaţie de recurenţă? Pentru a determina numărul minim de înmulţiri elementare pentru calculul produsului AixAi+1x...xAj, fixăm poziţia de parantezare k în toate modurile posibile (între i şi j-1), şi alegem varianta care ne conduce la minim. Pentru o poziţie k fixată, costul parantezării este egal cu numărul de înmulţiri elementare necesare pentru calculul produsului AixAi+1x...xAk, la care se adaugă numărul de înmulţiri elementare necesare pentru calculul produsului Ak+1x...xAj şi costul înmulţirii celor două matrice rezultate (di-1dkdj).
- Observăm că numai jumătatea de deasupra diagonalei principale din M este utilizată. Pentru a construi soluţia optimă este utilă şi reţinerea indicelui k, pentru care se obţine minimul. Nu vom considera un alt tablou, ci-l vom reţine, pe poziţia simetrică faţă de diagonala principală (M[j][i]).
- Rezolvarea recursivă a relaţiei de recurenţă de mai sus este ineficientă, datorită faptului că subproblemele de suprapun, deci o abordare recursivă ar conduce la rezolvarea aceleiaşi subprobleme de mai multe ori. Prin urmare vom rezolva relaţia de recurenţă în mod bottom-up: (determinăm parantezarea optimală a produselor de două matrice, apoi de 3 matrice, 4 matrice, etc).
- long M[NMax][NMax];
- void dinamic()
- { int nr, i, j, k, kmin;
- long min, Infinit=1000000000;
- for (nr=2; nr<=n; nr++) //nr=cate matrice se inmultesc
- for (i=1; i<=n-nr+1; i++)
- {j=i+nr-1;
- //se inmultesc nr matrice, de la Ai la Aj
- for (k=i, min=Infinit; k<j; k++)
- //determin minimul si pozitia sa
- if (min>M[i][k]+M[k+1][j]+d[i-1]*d[k]*d[j])
- {min=M[i][k]+M[k+1][j]+d[i-1]*d[k]*d[j];
- kmin=k;}
- M[i][j]=min; M[j][i]=kmin; }
- }
- Reconstituirea soluţiei optime se face foarte uşor în mod recursiv, utilizând informaţiile reţinute sub diagonala principală în matricea M:
- void afisare(int i, int j)
- {//afiseaza parantezarea optimala a produsului Aix...xAj
- if (i==M[j][i]) cout<<"A"<<i;
- else {cout<<"("; afisare(i,M[j][i]); cout<<")";}
- cout<<"x";
- if (j==M[j][i]+1) cout<<"A"<<j;
- else {cout<<"("; afisare(M[j][i]+1,j); cout<<")";}
- }
- 2. Subşir crescător maximal
- Fie un şir A=(a1, a2, ..., an). Numim subşir al şirului A o succesiune de elemente din A, în ordinea în care acestea apar în A: ai1, ai2, ..., aik, unde 1i1<i2<...<ikn. Determinaţi un subşir crescător al şirului A, de lungime maximă.
- Exemplu
- Pentru A=(8,3,6,50,10,8,100,30,60,40,80) o soluţie poate fi:
- ( 3,6, 10, 30,60, 80).
- Soluţie
- Fie Ai1=(ai1ai2 ...aik) cel mai lung subşir crescător al lui şirului A. Observăm că el coincide cu cel mai lung subşir crescător al şirului (ai1, ai1+1, ..., an). Evident Ai2=(ai2ai3 ...aik) este cel mai lung subşir crescător al lui (ai2, ai2+1, ..., an), etc. Prin urmare, o subproblemă a problemei iniţiale constă în determinarea celui mai lung subşir crescător care începe cu ai,i{1,.., n}. Subproblemele nu sunt independente: pentru a determina cel mai lung subşir crescător care incepe cu ai, este necesar să determinăm cele mai lungi subşiruri crescătoare care încep cu aj, aiaj, j{i+1,.., n}.
- Pentru a reţine soluţiile subproblemelor vom considera doi vectori suplimentari l şi poz, fiecare cu câte n componente, având semnificaţia:
- l[i]=lungimea celui mai lung subşir crescător care începe cu a[i];
- poz[i]=poziţia elementului care urmează după a[i] în cel mai lung subşir crescător care începe cu a[i], dacă un astfel de element există, sau -1 dacă un astfel de element nu există.
- Relaţia de recurenţă care caracterizează substructura optimală a problemei este:
- l[n]=1; poz[n]=-1;
- l[i]=max{1+l[j]|a[i]a[j]}
- j=i+1,n
- poz[i]= indicele j pentru care se obţine maximul l[i].
- Rezolvăm relaţia de recurenţă în mod bottom-up:
- int i, j;
- l[n]=1; poz[n]=-1;
- for (i=n-1; i>0; i--)
- for (l[i]=1, poz[i]=-1, j=i+1; j<=n; j++)
- if (a[i] <= a[j] && l[i]<1+l[j])
- {l[i]=1+l[j]; poz[i]=j;}
- Pentru a determina soluţia optimă a problemei, determinăm maximul din vectorul l, apoi afişăm soluţia, începând cu poziţia maximului şi utilizând informaţiile memorate în vectorul poz:
- //determin maximul din vectorul l
- int max=l[1], pozmax=1;
- for (int i=2; i<=n; i++)
- if (max<l[i]) {max=l[i]; pozmax=i;}
- cout<<"Lungimea celui mai lung subsir crescator: " <<max;
- cout<<"\nCel mai lung subsir:\n";
- for (i=pozmax; i!=-1; i=poz[i])
- cout<<a[i]<<' ';
- 3. Sumă în triunghi
- Sa considerăm un triunghi format din n linii (1<n100), fiecare linie conţinând numere întregi din domeniul [1,99], ca în exemplul următor:
- 7
- 3 8
- 8 1 0
- 2 7 4 4
- 4 5 2 6 5
- Problema constă în scrierea unui program care să determine cea mai mare sumă de numere aflate pe un drum între numărul de pe prima linie şi un număr de pe ultima linie. Fiecare număr din acest drum este situat sub precedentul, la stânga sau la dreapta acestuia. (IOI, Suedia 1994)
- Soluţie
- Vom reţine triunghiul într-o matrice pătratică T, de ordin n, sub diagonala principală. Subproblemele problemei date constau în determinarea sumei maxime care se poate obţine din numere aflate pe un drum între numărul T[i][j], până la un număr de pe ultima linie, fiecare număr din acest drum fiind situat sub precedentul, la stânga sau la dreapta sa. Evident, subproblemele nu sunt independente: pentru a calcula suma maximă a numerelor de pe un drum de la T[i][j] la ultima linie, trebuie să calculăm suma maximă a numerelor de pe un drum de la T[i+1][j] la ultima linie şi suma maximă a numerelor de pe un drum de la T[i+1][j+1] la ultima linie.
- Pentru a reţine soluţiile subproblemelor, vom utiliza o matrice suplimentară S, pătratică de ordin n, cu semnificaţia
- S[i][j]= suma maximă ce se poate obţine pe un drum de la T[i][j] la un element de pe ultima linie, respectand condiţiile problemei.
- Evident, soluţia problemei va fi S[1][1].
- Relaţia de recurenţă care caracterizează substructura optimală a problemei este:
- S[n][i]=T[n][i], i{1,2,...,n}
- S[i][j]=T[i][j]+max{S[i+1][j], S[i+1][j+1]}
- Rezolvăm relaţia de recurenţă în mod bottom-up:
- int i, j;
- for (i=1; i<=n; i++) S[n][i]=T[n][i];
- for (i=n-1; i>0; i--)
- for (j=1; j<=i; j++)
- {S[i][j]=T[i][j]+S[i+1][j];
- if (S[i+1][j]<S[i+1][j+1])
- S[i][j]=T[i][j]+S[i+1][j+1]);}
- Exerciţiu
- Afişaţi şi drumul în triunghi pentru care se obţine soluţia optimă.
- 4. Subşir comun maximal
- Fie X=(x1, x2, ..., xn) şi Y=(y1, y2, ..., ym) două şiruri de n, respectiv m numere întregi. Determinaţi un subşir comun de lungime maximă.
- Exemplu
- Pentru X=(2,5,5,6,2,8,4,0,1,3,5,8) şi Y=(6,2,5,6,5,5,4,3,5,8) o soluţie posibilă este: Z=(2,5,5,4,3,5,8)
- Soluţie
- Notăm cu Xk=(x1, x2, ..., xk) (prefixul lui X de lungime k) şi cu Yh=(y1, y2, ..., yh) prefixul lui Y de lungime h. O subproblemă a problemei date constă în determinarea celui mai lung subşir comun al lui Xk, Yh. Notăm cu LCS(Xk,Yh) lungimea celui mai lung subşir comun al lui Xk, Yh. Utilizând aceste notaţii, problema cere determinarea LCS(Xn,Ym), precum şi un astfel de subşir.
- Observaţie
- 1. Dacă Xk=Yh atunci LCS(Xk,Yh)=1+LCS(Xk-1,Yh-1).
- 2. Dacă XkYh atunci LCS(Xk,Yh)=max(LCS(Xk-1,Yh), LCS(Xk,Yh-1)).
- Din observaţia precedentă deducem că subproblemele problemei date nu sunt independente şi că problema are substructură optimală.
- Pentru a reţine soluţiile subproblemelor vom utiliza o matrice cu n+1 linii şi m+1 coloane, denumită lcs. Linia şi coloana 0 sunt utilizate pentru iniţializare cu 0, iar elementul lcs[k][h] va fi lungimea celui mai lung subşir comun al şirurilor Xk şi Yh.
- Vom caracteriza substructura optimală a problemei prin următoarea relaţie de recurenţă:
- lcs[k][0]=lcs[0][h]=0, k{1,2,..,n}, h{1,2,..,m}
- lcs[k][h]=1+lcs[k-1][h-1], dacă x[k]=y[h]
- max{lcs[k][h-1], lcs[k-1][h]}, dacă x[k]y[h]
- Rezolvăm relaţia de recurenţă în mod bottom-up:
- for (int k=1; k<=n; k++)
- for (int h=1; h<=m; h++)
- if (x[k]==y[h])
- lcs[k][h]=1+lcs[k-1][h-1];
- else
- if (lcs[k-1][h]>lcs[k][h-1])
- lcs[k][h]=lcs[k-1][h];
- else
- lcs[k][h]=lcs[k][h-1];
- Deoarece nu am utilizat o structură de date suplimentară cu ajutorul căreia să memorăm soluţia opţimă, vom reconstitui soluţia optimă pe baza rezultatelor memorate în matricea lcs. Prin reconstituire vom obţine soluţia în ordine inversă, din acest motiv vom memora soluţia într-un vector, pe care îl vom afişa de la sfârşit către început:
- cout<<"Lungimea subsirului comun maximal: " <<lcs[n][m];
- int d[100];
- cout<<"\nCel mai lung subsir comun este: \n";
- for (int i=0, k=n, h=m; lcs[k][h]; )
- if (x[k]==y[h])
- {d[i++]=x[k];k--; h--;}
- else
- if (lcs[k][h]==lcs[k-1][h])
- k--;
- else
- h--;
- for (k=i-1;k>=0; k--)cout<<d[k]<<' ';
- 5. Stivă de jetoane
- Un joc este constituit dintr-o stivă de n (n1000) jetoane, de două culori. Jetoanele sunt numerotate de la 1 la n, jetonul cu numărul 1 fiind cel de la vârful stivei. Cei doi jucători (să-i numim Ana şi Barbu) mută alternativ. La o mutare, un jucător poate lua din stivă oricâte jetoane (cel puţin unul), cu condiţia ca toate jetoanele luate să fie de aceeaşi culoare. Câştigă jucătorul care ia ultimul jeton. Să presupu nem că întotdeauna Ana face prima mutare.
- Scrieţi un program care să determine dacă Ana are strategie sigură de câştig şi dacă da, să afişeze pe ecran mutările Anei (câte jetoane ia din stivă atunci când îi vine rândul). Programul va citi de la tastatură mutările lui Barbu.
- Soluţie
- Vom reţine culorile jetoanelor într-un vector c[]. Iniţializarea configuraţiei de joc constă din citirea numărului de jetoane şi generarea aleatoare a culorilor acestora, codificând prima culoare cu 0 şi cea de a doua culoare cu 1.
- #define NMax 1002
- int n, c[NMax];
- void Init()
- {cout<<"n="; cin>>n;
- randomize();
- for (int i=1; i<=n; i++) c[i]=random(2);
- cout<<"Stiva de jetoane este ";
- for (i=1; i<=n; i++) cout<<c[i];
- cout<<endl; }
- Subproblemele problemei date constau în determinarea existenţei unei strategii sigure de câştig pentru jucătorul care face prima mutare pentru o stivă constituită din jetoanele i..n.
- Pentru a reţine soluţiile subproblemelor, vom utiliza un vector S[], având următoarea semnificaţie: S[i]=1, dacă jucătorul care extrage jetonul i are strategie sigură de câştig şi 0 altfel. Evident, dacă S[1]=1, deducem că Ana are strategie sigură de câştig.
- Caracterizăm substructura optimale a soluţiei prin următoarea relaţie de recurenţă:
- S[n]=1;
- Dacă c[i]c[i+1], atunci S[i]=1-S[i+1].
- Dacă c[i]=c[i+1], atunci S[i]=1 (în cazul în care S[i+1]=1, jucătorul va lua şi jetonul i pe lângă jetoanele care îî asigură câştigul pentru i+1..n; dacă S[i+1]=0, atunci jucătorul va lua numai jetonul i).
- Rezolvăm această relaţie de recurenţă în mod bottom-up:
- int S[NMax];
- void Dinamic()
- {S[n]=1;
- for (int i=n-1; i>0; i--)
- if (c[i+1]!=c[i]) S[i]=1-S[i+1];
- else S[i]=1; }
- În cazul în care Ana are strategie sigură de câştig, pentru a vizualiza şi mutările care conduc la câştigarea jocului, utilizăm informaţiile deja memorate în S[]:
- if (!S[1])
- {cout<<"Ana nu are strategie sigura de castig!";
- return;}
- cout<<"Ana are strategie sigura de castig! Sa jucam!\n";
- for (int i=1; i<=n; )
- {for (int k=i; k<=n && S[k]; k++);
- //Ana ia jetoanele de la i la k
- cout<<"Ana ia: "<<k-i<<" jetoane\n";
- if (k>n)
- {cout<<"Ana a castigat!\n"; return;}
- //citim mutarea lui Barbu
- cout<<"Stiva ";
- for (int j=k; j<=n; j++) cout<<c[j];
- cout<<"\nBarbu muta: "; cin>>nr;
- //validez mutarea lui Barbu
- for (j=k+1; j<k+nr; j++)
- if (c[j]!=c[j-1])
- {cout<<"Mutare gresita! Barbu pierde!\n";
- return;}
- i=k+nr; }
- 7. Laser
- Se consideră o placă dreptunghiulară cu dimensiunile mn. Această placă trebuie tăiată în mn bucăţi mai mici, fiecare bucată fiind un pătrat cu dimensiunile 11. Întrucât placa este neomogenă, pentru fiecare bucată se indică densitatea dxy, unde x, y sunt coordonatele colţului stânga-jos al pătratului respectiv.
- Pentru operaţiile de tăiere se foloseşte un strung cu laser. Fiecare operaţie de tăiere include:
- fixarea unei plăci pe masa de tăiere;
- stabilirea puterii laserului în funcţie de densitatea materialului de tăiat;
- o singură deplasare a laserului de-a lungul oricărei drepte paralele cu una din axele de coordonate;
- scoaterea celor două plăci de pe masa de tăiere.
- Costul unei operaţii de tăiere se determină după formula c=dmax, unde dmax este densitatea maximă a bucăţilor 11 peste marginile cărora trece raza laserului. Evident, costul total T poate fi determinat adunând costurile individuale c ale tuturor operaţiilor de tăiere necesare pentru obţinerea bucăţilor 11.
- Scrieţi un program care calculează costul minim T.
- (Olimpiada Republicană de Informatică, Republica Moldova, 2001)
- Date de intrare
- Fişierul text LASER.IN conţ=ine pe prima linie numerele m şi n separate prin spaţiu. Următoarele m linii conţin câte n numere dxy separate prin spaţiu.
- Date de ieşire
- Fişierul text LASER.OUT conţine pe o singură linie numărul natural T.
- Exemplu
- LASER.IN
- LASER.OUT
- 3 5
- 1 1 1 1 5
- 1 7 1 1 1
- 1 1 1 6 1
- 52
- Restricţii
- m,nN, 2m,n20
- dxyN, 1dxy100
- Soluţie
- Subproblemele problemei date constau în tăierea unui dreptunghi din placa dată, care are colţul stânga-sus în poziţia (i, j), are lungimea l şi înălţimea h.
- Pentru a reţine soluţiile subproblemelor trebuie să utilizăm un tablou cu 4 dimensiuni Cnxmxnxm, cu semnificaţia C[i,j,h,l]=costul total de tăiere a unui unui dreptunghi din placa dată, care are colţul stânga-sus în poziţia (i, j), are lungimea l şi înălţimea h. Evident, soluţia problemei date va fi C[1,1,n,m].
- Deoarece nu avem spaţiu suficient, vom aloca parţial tabloul c în mod dinamic, şi îl vom iniţializa cu 0:
- int i, j, k, l, h;
- for (i=0; i<=n; i++)
- for (j=0; j<=m; j++)
- for (h=0; h<=n; h++)
- {c[i][j][h]=new int[MaxD];
- for (l=0; l<=m; l++) c[i][j][h][l]=0;}
- Pentru a tăia un dreptunghi din placa dată, care are colţul stânga-sus în poziţia (i, j), are lungimea l şi înălţimea h trebuie să executăm o primă tăietură completă. Aceasta poate fi trasată fie orizontal (între liniile k-1 şi k, unde k variază de la i+1 până la i+h-1), fie vertical, între coloanele k-1 şi k, unde k variază de la j+1 la j+l-1). Vom alege succesiv poziţia de tăiere k în toate modurile posibile şi vom reţine varianta care asigură optimul.
- j j+1 j+l-1
- i
- i+1
- ...
- k-1
- k
- ...
- i+h-1
- Tăietură orizontală
- j j+1 k-1 k j+l-1
- i
- i+1
- ...
- i+h-1
- Tăietură verticală
- Prin urmare putem caracteriza substructura optimală a problemei prin următoarea relaţie de recurenţă:
- C[i][j][1][1]=0; i{1,2,..,n}, j{1,2,..,m}
- C[i][j][h][l]=min
- {min{c[i][j][k-i][l]+c[k][j][h-k+i][l]+dmaxL(k,j,l)}//orizontal
- k=i+1,i+h-1
- min{c[i][j][h][k-j]+c[i][k][h][l-k+j]+dmaxC(k,i,h)}} //vertical
- k=j+1,j+l-1
- În relaţiile de recurenţă precedente am utilizat valorile:
- dmaxL(k,j,l), reprezentând densitatea maximă a bucăţilor 11 peste marginile cărora trece raza laserului, la o tăietură între liniile k-1 şi k, de lungime l, începând de la coloana j;
- dmaxC(k,i,h), reprezentând densitatea maximă a bucăţilor 11 peste marginile cărora trece raza laserului, la o tăietură între coloanele k-1 şi k, de lungime h, începând cu linia i.
- Calculul soluţiei optime în mod bottom-up:
- for (h=1; h<=n; h++)
- for (l=1; l<=m; l++)
- for (i=1; i<=n-h+1; i++)
- for (j=1; j<=m-l+1; j++)
- if (l>1 || h>1)
- {//determin c[i][j][h][l]
- c[i][j][h][l]=infinit;
- //taieturi orizontale
- for (k=i+1; k<i+h; k++)
- {a=c[i][j][k-i][l]+c[k][j][h-k+i][l]+dmaxL(k,j,l);
- if (c[i][j][h][l]>a) c[i][j][h][l]=a;}
- //taieturi verticale
- for (k=j+1; k<j+l; k++)
- {a=c[i][j][h][k-j]+c[i][k][h][l-k+j]+dmaxC(k,i,h);
- if (c[i][j][h][l]>a) c[i][j][h][l]=a;}
- }
- Observaţie
- O optimizare posibilă a algoritmului constă în evitarea apelurilor funcţiilor dmaxL() şi dmaxC(), prin precalcularea valorilor respective o singură dată şi memorarea lor în câte un tablou tridimensional. Implementaţi această optimizare!
- 8. Problema patronului
- Un patron de gogoşerie a cumpărat un calculator şi doreşte să înveţe să lucreze pe el. Pentru aceasta va umple un raft de cărţi din colecţia „Informatica în lecţii de 9 minute şi 60 secunde”. Raftul are lungimea L cm. Seria dispune de n titluri, numerotate 1, 2,..., n având respectiv grosimile de g1, g2,..., gn cm.
- Scrieţi un program care să selecteze titlurile pe care le va cumpăra patronul, astfel încât raftul să fie umplut complet (suma grosimilor cărţilor cumpărate să fie egală cu lungimea raftului) şi numărul cărţilor achiziţionate să fie maxim. Progra mul va afişa numărul cărţilor selectate, precum şi grosimile acestora. Dacă nu există soluţie, va fi afişat mesajul IMPOSIBIL. (ONI Suceava 1996, XI)
- Restricţii
- nN, 1n60
- LN,1L200
- giN*, gi30000, i{1,2,...,n}
- Timp maxim de execuţie: 1 secundă/test.
- Exemplu
- Soluţie
- Problema constă în selectarea unor elemente a căror sumă să fie egală cu L. În cazul în care există mai multe soluţii, este preferată soluţia cu număr maxim de elemente. O subproblemă a acestei probleme constă în selectarea unor elemente a căror sumă să fie egală cu S, SL.
- Pentru a reţine soluţiile subproblemelor vom utiliza un vector Nr, cu L+1 componente, având semnificaţia: Nr[S]=numărul maxim de titluri ce pot fi cumpărate pentru a umple un raft de lungime S (0SL) sau -1 (dacă nu putem umple un raft de lungime S). Pentru a reţine şi cărţile cumpărate, vom utiliza o matrice Uz cu L+1 linii şi n coloane, având semnificaţia L[S][i] este 1, dacă am utilizat titlul i pentru a umple optimal raftul de lungime S şi 0, în caz contrar.
- #define NMax 61
- #define LMax 201
- int n, L; //numarul de titluri si lungimea raftului
- int g[NMax]; //grosimile
- int Nr[LMax]; //numarul maxim de carti selectate
- int Uz[LMax][NMax]; //indicii titlurilor utilizate
- Să considerăm că ultimul titlu selectat pentru a umple un raft de lungime S este i. Prin urmare, în rest sunt selectate (obligatoriu în mod optim) cărţi a căror grosime totală trebuie să fie egală cu S-g[i]. Evident, pentru a putea alege titlul i, condiţia este ca acest titlu să nu fie deja utilizat pentru a umplerea restului raftului (de lungime S-g[i]). Alegerea titlului i trebuie să fie făcută de asemenea în mod optim (să maximizeze numărul total de cărţi selectate):
- Nr[0]=0;
- Nr[S]=max{-1, max{1+Nr[S-g[i]]|S-g[i]0 şi Nr[S-g[i]]-1 şi
- i=1,n Uz[S-g[i]][i]=0}
- Rezolvarea relaţiei de recurenţă:
- int S, k, i;
- for (S=1; S<=L; S++)
- for (Nr[S]=-1, i=1; i<=n; i++)
- if (g[i]<=S && Nr[S-g[i]]!=-1 && !Uz[S-g[i]][i] )
- if (Nr[S]<1+Nr[S-g[i]])
- {Nr[S]=1+Nr[S-g[i]];
- for (k=1;k<=n;k++) Uz[S][k]=Uz[S-g[i]][k];
- Uz[S][i]=1;}
- Pentru a afişa soluţia, utilizăm informaţiile memorate în tabloul Uz:
- if (Nr[L]==-1) cout<<"IMPOSIBIL";
- else
- {cout<<"Numarul maxim de carti este: "<<Nr[L]<<endl;
- for (int k=1; k<=n; k++)
- if (Uz[L][k]) cout <<g[k]<<" ";}
- 9. Telecomanda
- Cu ocazia olimpiadei naţionale de informatică, televiziunea locală organizează un nou joc în direct. Organizatorii utilizează un calculator, care generează şi afişează pe un monitor două numere de maxim 100 de cifre fiecare (X şi Y).
- Fiecare concurent dispune de o telecomandă pre vă zută cu un afişaj de o cifră şi cu anumite taste, ca în figura alăturată. Telecomanda are şi o memorie, în care sunt reţinute în ordine cifrele obţinute de concurenţi.
- Cifrele primului număr (X) sunt afişate succesiv pe afişajul telecomenzii fiecărui concurent, în ordine de la stânga la dreap ta. Concurenţii trebuie să transforme primul număr, obţinând în memoria telecomenzii proprii pe cel de al doilea, utilizând tastele pe care le au la dispoziţie pe telecomandă. După efectuarea unei operaţii asupra cifrei curente (cea de pe afişaj), pe afişaj apare automat urmă toarea cifră din X (dacă mai există). Efectele apăsării tastelor sunt următoarele:
- Taste acţionate
- Efect
- + urmat de o cifră
- Se generează suma dintre cifra de pe afişaj şi cifra tastată (operaţie posibilă doar dacă suma este tot o cifră). Cifra sumă este reţinută în memorie.
- – urmat de o cifră
- Se generează diferenţa dintre cifra de pe afişaj şi cifra tastată (operaţie posibilă doar dacă se obţine tot o cifră). Cifra obţinută este reţinută în memorie.
- * urmat de o cifră
- Se reţine în memorie valoarea tastei care se acţionează după tasta *. Deoarece asupra cifrei curente din X nu se efectuează nici o operaţie, aceasta nu dispare de pe afişaj.
- /
- Se şterge cifra curentă din X
- #
- Se şterg din X cifra curentă şi toate cifrele care urmează, până la sfârşit.
- =
- Se copiază în memorie cifra curentă.
- Acţiunea se încheie atunci când toate cifrele lui X au fost prelucrate. Am obţinut o soluţie când în memoria telecomenzii se află cifrele numărului Y. O soluţie este optimă dacă numărul de taste acţionate este minim. Câştigătorii jocului sunt acei concurenţi care descoperă o soluţie optimă.
- Date fiind X şi Y, scrieţi un program care să determine o soluţie optimă de transformare a numărului X în numărul Y. (ONI, Bacău 2001, XI-XII)
- Date de intrare
- Fişier de intrare TELE.IN conţine două linii:
- X
- Y
- Date de ieşire
- Fişier de ieşire TELE.OUT conţine două linii:
- min
- t1t2...tmin
- unde:
- min este un număr natural nenul, reprezentând numărul minim de taste acţionate pentru transformarea lui X în Y.
- t1t2...tmin este o succesiune de min caractere, care reprezintă tastele acţionate; între caractere nu se vor pune separa tori.
- Exemplu
- TELE.IN TELE.OUT
- 372 4
- 78 /=+6
- Timp maxim de execuţie/test: 1 secundă
- Soluţie
- Să notăm cu m numărul de cifre din X şi cu n numărul de cifre din Y. De asemenea vom nota Xi sufixul care începe cu cifra i din X (secvenţa de cifre XiXi+1...Xm) şi cu Yj sufixul care începe cu cifra j din Y (secvenţa de cifre YjYj+1...Yn). Subproblemele problemei date constau în determinarea transformării de cost minim a lui Xi în Yj, i{1,2,...,m} şi j{1,2,...,n}.
- Pentru a reţine soluţiile subproblemelor vom utiliza două matrice cm şi o, fiecare cu m linii şi n coloane, având următoarea semnificaţie:
- cm[i][j] = numărul minim de acţionări de taste necesar pentru a transforma Xi în Yj.
- o[i][j] = prima operaţie ce va fi executată pentru a transforma optimal Xi în Yj.
- typedef char Operatie[3];
- char x[DimMax], y[DimMax];
- int cm[DimMax][DimMax];
- Operatie o[DimMax][DimMax];
- int n, m;
- Evident, cm[1][1] reprezintă numărul minim de acţionări de taste necesar pentru a transforma numărul X în numărul Y.
- Relaţia de recurenţă carecaracterizează substructura optimală a problemei este:
- cm[i][j]=min
- {1+cm[i+1][j], //operatia /
- 2+cm[i][j+1], //operatia *Y[j]
- 2+cm[i+1][j+1], //operatia - X[i]-Y[j], daca X[i]>Y[j]
- 2+cm[i+1][j+1], //operatia + Y[j]-X[i], daca X[i]<Y[j]
- 1+cm[i+1][j+1], //operatia =
- 1+cm[m+1,j]} //operatia #
- Secvenţa de iniţializare:
- void Init()
- { m=strlen(x); n=strlen(y);
- for (int i=1; i<=m; i++)
- {cm[i][n+1]=1; strcpy(o[i][n+1],"#"); }
- for (i=1; i<=n; i++)
- {cm[m+1][i]= 2*(n-i+1);
- for (int j=i; j<=n; j++)
- {o[m+1][j][0]='*';
- o[m+1][j][1]=y[j];o[m+1][j][2]=NULL;}
- }
- }
- Rezolvăm relaţia de recurenţă în mod bottom-up:
- Operatie omin;
- int min;
- for (int j=n; j>0; j--)
- for (int i=m; i>0; i--)
- {min=1+cm[i+1][j]; strcpy(omin,"/");
- if (min>2+cm[i][j+1])
- {min=2+cm[i][j+1];
- omin[0]='*'; omin[1]=y[j]; omin[2]=NULL;}
- if (x[i]>y[j])
- {if (min>2+cm[i+1][j+1])
- {min=2+cm[i+1][j+1];
- omin[0]='-'; omin[1]=x[i]-y[j]+'0';
- omin[2]=NULL;}
- }
- else
- if (x[i]<y[j])
- {if (min>2+cm[i+1][j+1])
- {min=2+cm[i+1][j+1];
- omin[0]='+'; omin[1]=y[j]-x[i]+'0';
- omin[2]=NULL;}
- }
- else
- {if (min>1+cm[i+1][j+1])
- {min=1+cm[i+1][j+1]; strcpy(omin,"=");}
- }
- if (min>1+cm[m+1][j])
- {min=1+cm[m+1][j]; strcpy(omin,"#");}
- cm[i][j]=min;
- strcpy(o[i][j],omin);
- }
- O soluţie optimă se obţine utilizând matricea o, a operaţiilor efectuate la fiecare pas.
- ofstream ui("tele.out");
- ui<<cm[1][1]<<endl;
- for (int i=1,j=1; i<=m+1 && j<=n+1 && !(i==m+1 && j==n+1);)
- {ui<<o[i][j];
- if (o[i][j][0]=='+'||o[i][j][0]=='-'||o[i][j][0]=='=')
- {i++; j++; }
- else
- if (o[i][j][0] =='*') j++;
- else
- if (o[i][j][0] =='/') i++;
- else i=m+1;
- }
- ui.close();
- 10. Codificare optimală
- Fie un text de lungime maximă 100, ce conţine doar litere. Textul poate fi codificat, înlocuind apariţiile consecutive ale subşirurilor sale cu subşirul urmat de numărul său de apariţii.
- Exemplu
- Textul T="aaacaaacbbdefdef" poate fi codificat: "a3c1a3c1b2def2" dar şi "aaac2b2def2". Evident, cel de al doilea mod de codificare este mai scurt, deci mai convenabil.
- Scrieţi un program care să codifice optimal un text dat (codul rezultat să fie de lungime minimă).
- Soluţie
- Spaţiul subproblemelor problemei iniţiale este format din determinarea unei codificări optimale pentru caracterele din text de la i până la j (T[i..j]), 0ij<n, unde n este lungimea textului. Evident, subproblemele se suprapun. De exemplu, determinarea codificării optime pentru T[i..j], necesită determinarea unor codificări optime pentru T[i..k] şi pentru T[k+1..j], k{0,1,..., j-1}.
- Pentru a memora soluţiile subproblemelor, vom utiliza o matrice l, pătratică de ordin n, având semnificaţia l[i][j] = lungimea codificarii optime pentru T[i..j]; 0ij<n. Observaţi că este utilizată numai jumătatea de deasupra diagonalei principale.
- Problema are substructură optimală, caracterizată de următoarea relaţie de recurenţă:
- Orice caracter x se codifică pe două poziţii (x1), deci:
- l[i][i]=2, i{0,1,..., n-1}
- l[i][j]=min {j-i+2, minI, minII}
- unde:
- j-i+2 provine din codificarea întregului şir, urmat de 1
- minI=min{l[i][k]+l[k+1][j]}
- k=i,j-1
- Codificăm optimal T[i..j] concatenând codificările optimale ale şirurilor T[i..k] şi T[k+1..j] (poziţia k{i, i+1,...,j-1} se alege în mod optimal)
- minII=min{strlen(s)+NrCifre(k)}, unde s subşir al lui T[i..j] astfel încât T[i..j]=ss..s (de k ori). Deci T[i..j] se codifică sk.
- Deoarece jumătatea de sub diagonala principală din matricea l este neutilizată, pentru a putea reconstitui soluţia optimă, o vom utiliza astfel:
- l[j][i]=0, dacă l[i][j]=j-i+2
- l[j][i]=k, unde k este poziţia de splitare a textului pentru l[i][j]=minI
- l[j][i]=-k, unde k este lungimea subşirului s care se repetă, pentru T[i][j]=minII.
- Rezolvarea relaţiei de recurenţă:
- for (int i=0; i<n; i++) l[i][i]=2;
- for (int d=2; d<=n; d++) //codific subsiruri de lungime d
- for (i=0; i<=n-d; i++) //care incep la pozitia i
- {int j=i+d-1; //si se termina la pozitia j
- //cazul I- codificarea este intregul sir urmat de 1
- l[i][j]=d+1; l[j][i]=0;
- //cazul II
- for (int k=i; k<j; k++)
- if (l[i][j]>l[i][k]+l[k+1][j])
- {l[i][j]=l[i][k]+l[k+1][j];
- l[j][i]=k;}// pozitia optima de splitare
- //cazul III
- for (k=1; k<=d/2; k++)
- if (d%k==0) //determin un subsir de lungime k
- if (SeRepeta(i,j,k))
- {l[i][j]=k+NrCifre(d/k);
- l[j][i]=-k; //retin lungimea subsirului
- break;}
- }
- Observaţi că am utilizat funcţia NrCifre() care determină numărul de cifre dintr-un număr natural, precum şi funcţia SeRepeta():
- int SeRepeta (int i, int j, int k)
- {/*verifica daca sirul T[i..j] este format prin concatenarea succesiva a lui T[i..i+k-1] */
- char s[DimMax], s1[DimMax];
- strncpy(s,T+i,k); s[k]=NULL; s1[k]=NULL;
- for (int h=i+k; h<=j; h+=k)
- {strncpy(s1,T+h, k);
- if (strcmp(s,s1)) return 0;}
- return 1;}
- Afişarea soluţiei optime o vom realiza prin apelarea funcţiei recursive Afisare(0,n-1):
- ofstream ui("cod.out");
- void Afisare(int i, int j)
- {
- if (i==j) cout<<T[i]<<1; //un singur caracter
- else
- {int k=l[j][i];
- char s[DimMax];
- if (!k) // cazul I
- {strncpy(s,T+i,j-i+1); s[j-i+1]=NULL;
- cout<<s<<1; }
- else
- if (k>0) //cazul II
- {Afisare (i, k);
- Afisare (k+1,j);}
- else //cazul III
- {strncpy(s,T+i,-k); s[-k]=NULL;
- cout<<s<<(j-i+1)/(-k);}
- }
- }
- 12. Florărie
- Presupunem că aveţi o florărie şi că doriţi să aranjaţi vitrina într-un mod cât mai plăcut. Aveţi F buchete de flori de feluri diferite şi cel puţin tot atâtea vase, aranjate pe un raft. Vazele sunt lipite de raft, şi sunt numerotate în ordine, de la stânga la dreapta, de la 1 la V, unde V este numărul de vaze. Mai exact vaza 1 este cea mai din stânga, iar vaza V cea mai din dreapta. Buchetele sunt şi ele numerotate distinct, cu numere între 1 şi F. Aceste numere de identificare a buchetelor au o semnificaţie: ele determină ordinea de apariţie cerută pentru buchete în vaze. Mai exact, buchetul i trebuie să fie într-o vază din stânga vazei care conţine buchetul j, dacă i<j.
- Să presupunem, de exemplu, că aveţi un buchet de azalee (cu numărul de identificare 1) un buchet de begonii (cu numărul de identificare 2) şi un buchet de trandafiri (cu numărul de identificare 3). Acum, toate buchetele trebuie puse în vaze, astfel încât ordinea numerelor lor de identificare să se păstreze. Buchetul de azalee trebuie să fie într-o vază din stânga begoniilor, care trebuie să fie într-o vază din stânga trandafirilor. Dacă există mai multe vaze decât buchete, cele în plus vor rămâne goale. O vază poate conţine un singur buchet de flori.
- Fiecare vază are o caracteristică proprie (asemănător florilor). Prin urmare, aşezănd un buchet de flori într-o anumită vază, obţineţi un anumit efect estetic, exprimat printr-o valoare întreagă. Valorile estetice sunt reprezentate sub forma unui tablou, ca în exemplul de mai jos. Dacă o vază rămâne goală, valoarea estetică este 0.
- V A Z E
- 1
- 2
- 3
- 4
- 5
- Buchete
- 1 (azalee)
- 7
- 23
- -5
- -24
- 16
- 2 (begonii)
- 5
- 21
- -4
- 10
- 23
- 3 (trandafiri)
- -21
- 5
- -4
- -20
- 20
- Conform acestui tabel, azaleele, de exemplu, vor arăta grozav în vaza 2 şi groaznic în vaza 4.
- Pentru a obţine cel mai plăcut efect, trebuie să maximizaţi suma valorilor estetice ale vazelor, păstrând ordinea buchetelor. Dacă există mai multe soluţii, se cere numai una. (IOI Turcia 1999)
- Restricţii
- 1≤F≤100 unde F este numărul de buchete de flori.
- F≤V≤100 unde V este numărul de vaze.
- -50Aij50 unde Aij este valoarea estetică care se obţine punând buchetul i în vaza j.
- Timp maxim de execuţie 2 secunde / test.
- Date de intrare
- Fişierul de intrare se numeşte flower.in. Prima linie conţine două numere: F V. Fiecare din următoarele F linii conţine câte V numere întregi, astfel încât Aij este al j-lea număr de pe linia (i+1) din fişierul de intrare.
- Date de ieşire
- Fişierul de ieşire flower.out conţine două linii. Prima linie conţine suma valorilor estetice a aranjamentului floral. A doua linie reprezintă aranjamentul floral, ca o listă de F numere, astfel încât cel de al k-lea număr de pe linie identifică vaza în care este pus buchetul k.
- Exemplu
- flower.in
- flower.out
- 3 5
- 7 23 –5 –24 16
- 5 21 -4 10 23
- -21 5 -4 -20 20
- 53
- 2 4 5
- Soluţie
- Subproblemele problemei date constau în amplasarea optimă (cu maximizarea sumei valorilor estetice) a buchetelor 1..i în vazele 1..j, respectând ordinea buchetelor (i{1,2,...,F}, j{i,...,V-F+i}).
- Pentru a reţine soluţiile subproblemelor vom utiliza o matrice c cu F linii şi V coloane (c[i][j]=valoarea estetică optimă care se poate obţine amplasând buchetele 1..i în vazele 1..j, respectând ordinea buchetelor. Evident, valoarea estetică optimă se obţine în c[F][V]. Pentru reconstituirea soluţiei optime, vom utiliza o matrice poz cu F linii şi V coloane (poz[i][j]= vaza în care plasăm buchetul i, într-o amplasare estetică optimă a buchetelor 1..i în vazele 1..j).
- Pentru a amplasa optim buchetele 1..i în vazele 1..j, respectând ordinea buchetelor (i{1,2,...,F}, j{i,...,V-F+i}) avem două posibilităţi (dintre care o alegem pe cea mai convenabilă): fie amplasăm buchetul i în vaza j şi amplasăm optimal buchetele 1..i-1 în vazele 1..j-1, fie amplasăm buchetele 1..i în vazele 1..j-1. Prin urmare, caracterizăm substructura optimală a problemei prin următoarea relaţie de recurenţă:
- c[i][i-1]=-;, i{1,2,...,F}
- c[0][j]=0; j{0,...,V}
- c[i][j]=max{A[i][j]+c[i-1][j-1], c[i][j-1]}, i{1,2,...,F}, j{i,...,V-F+i}
- Pentru implementare observăm putem iniţializa c[i][j] cu valoarea Aij, astfel încât să nu mai fie necesar să utilizăm o matrice suplimentară A. Rezolvăm relaţia de recurenţă în mod bottom-up astfel:
- int i, j;
- for (i=1; i <= F; i++) c[i][i-1]=MINF;
- for (i=1; i <= F; i++)
- for (j=i; j <= (V - F + i); j++)
- if (c[i-1][j-1]+c[i][j]>c[i][j-1])
- {c[i][j] += c[i-1][j-1];
- poz[i][j]=j;}
- else
- {c[i][j]=c[i][j-1];
- poz[i][j]=poz[i][j-1];}
- Afişarea soluţiei o vom face utilizând valorile memorate în matricea poz:
- ofstream ui("flower.out");
- ui<<c[F][V]<<endl;
- int sol[MaxNr];
- for (int i=F, j=V; i>0; j--)
- if (poz[i][j]==j)
- {sol[i]=j; i--;}
- for (i=1; i<=F; i++) ui<<sol[i]<<' ';
- ui.close();
- 13. Vin bun
- La un depozit specializat din Recaş sosesc, pe rând, n clienţi care solicită fiecare o cantitate dată de Cabernet. În butoiul din magazinul de deservire (considerat de capacitate nelimitată) nu se găseşte iniţial nici o picătură de vin. Dan Şeptică, administratorul depozitului, are un algoritm propriu de deservire a clienţilor: în funcţie de ceea ce are în butoi, dar şi de inspiraţia de moment, el poate să răspundă: „Vă ofer întreaga cantitate cu cea mai mare plăcere!” sau „Nu vă pot oferi acum ceea ce doriţi, reveniţi cu solicitarea altădată!”.
- Pe clientul servit îl eliberează de grija banilor corespunzători costului licorii cumpărate, iar pe cel refuzat îl salută politicos şi are grijă ca , imediat ce a plecat clientul, să coboare şi să aducă în butoiul din magazin exact cantitatea solicitată de clientul respectiv (cel ce nu a fost servit) .
- Clienţii sunt restaurante de lux şi nu cumpăra mai mult de 1 hectolitru.
- Cunoscând cele n cantităţi cerute de clienţi, să se determine un mod de a răspunde solicitărilor astfel încât, în final, cantitatea de vin vânduta să fie maximă.
- Date de intrare
- Din fişierul de intrare CERERI.IN se citesc:
- n – numărul de clienţi (n600);
- c1 c2 ... cn – cantităţile (în litri) cerute de clienţi, în ordinea sosirii lor.
- Date de ieşire
- În fişierul VANZARI.OUT se va scrie cantitatea vândută (tot în litri).
- Exemplu
- CERERI.IN
- VANZARI.OUT
- 4
- 5 3 4 2
- 6
- Interpretare
- Acţiunile lui Septică sunt: refuză primul client şi pune 5 litri în butoi, îl refuză pe al doilea şi mai pune încă 3 litri în butoi, iar pe următorii doi clienţi îi serveşte , realizând o vânzare de 6 litri. (ONI Timişoara 1997, X)
- Soluţie
- Subproblemele problemei date constau în determinarea cantităţii maxime de vin ce poate fi vândută luând în considerare cererile clienţilor i..n, în ipoteza că iniţial avem în butoi o cantitate j. Soluţiile acestor subprobleme le vom reţine într-o matrice v.
- Relaţia de recurenţă o obţinem astfel:
- v[i][0]=0, i{1,2,...,n}
- v[i][j]= max{v[i+1][j+c[i]] (cazul în care clientul i este refuzat)
- c[i]+v[i+1][j-c[i]], dacă j≥c[i]
- (cazul în care clientul i este servit)}
- Soluţia problemei iniţiale o vom obţine în v[1][0].
- O problemă de implementare o constituie dimensiunile matricei v: i variază de la 1 la n, deci numărul de linii este maxim 600). Numărul de coloane este determinat de cantitatea maximă care se poate acumula în butoi (în cazul cel mai defavorabil cei 600 de clienţi comandă fiecare câte 100 de litri), deci numărul maxim de coloane ar fi 60000. Nu putem aloca în memorie o matrice de 600x60000, dar observăm că pentru determinarea liniei i din matricea v este necesară numai linia i+1. Prin urmare este suficient să utilizăm doi vectori de 60000 de componente – v1 pentru a reţine linia precedentă (linia i+1) şi v2 pentru a calcula linia curentă (linia i). Aceşti doi vectori vor fi alocaţi dinamic, numărul de elemente alocate fiind max (suma tuturor cantităţilor cerute de clienţi):
- unsigned *v1,*v2;
- v1=new unsigned[max];
- v2=new unsigned[max];
- if(!v1 || !v2)
- { cout<<"Nu s-a putut aloca memorie.";
- exit(0); }
- for(i=0; i<max; i++) v1[i]=0;
- Rezolvarea relaţiei de recurenţă:
- unsigned i, j, *aux;
- for(i=n; i>=1; i--)
- { for(j=0;j<c[i]; j++) v2[j]=v1[j+c[i]];
- for (; j<max-c[i]; j++)
- { v2[j]=v1[j+c[i]];
- if (v2[j]<c[i]+v1[j-c[i]])
- { v2[j]=c[i]+v1[j-c[i]]; } }
- aux=v1; v1=v2; v2=aux;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Componente tare conexe (SCC)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #define foreach(V) for(vector<int>::iterator it=V.begin(),stop=V.end();it!=stop;++it)
- int n;
- int m;
- vector<int> G[100000+10];
- vector<int> sol[100000+10];
- bool in_stack[100000+10];
- stack<int> st;
- bool viz[100000+10];
- int min_lev[100000+10];
- int nr=0;
- void dfs_tarjan(int nod)
- {
- st.push(nod);
- in_stack[nod]=true;
- viz[nod]=true;
- min_lev[nod]=idx;
- int initial_min_lev=idx;
- idx++;
- foreach(G[nod]) {
- if(!viz[*it]) {
- dfs_tarjan(*it);
- min_lev[nod]=min(min_lev[nod],min_lev[*it]);
- } else if(in_stack[*it])
- min_lev[nod]=min(min_lev[nod],min_lev[*it]);
- }
- if(min_lev[nod]==initial_min_lev) {
- int x;
- do {
- x=st.top();
- st.pop();
- sol[nr].push_back(x);
- in_stack[x]=false;
- } while(x!=nod);
- nr++;
- }
- }
- //bool cmp(vector<int> a, vector<int> b)
- //{
- // return a[0]<b[0];
- //}
- int main()
- {
- fin>>n>>m;
- for(; m; --m) {
- int x,y;
- fin>>x>>y;
- G[x].push_back(y);
- }
- idx=0;
- for(int i=1; i<=n; ++i)
- if(!viz[i])
- dfs_tarjan(i);
- fout<<nr<<'\n';
- // for(int i=0;i<nr;++i,cerr<<'\n')
- // {
- //// cerr<<sol[nr].size()<<' ';
- // foreach(sol[i])
- // cerr<<*it<<' ';
- // }
- // for(int i=0;i<nr;++i) {
- // sort(sol[i].begin(),sol[i].end()); //sortare degeaba
- // }
- // sort(sol,sol+nr,cmp);//sortare degeaba
- for(int i=0;i<nr;++i,fout<<'\n')
- {
- // fout<<sol[i].size()<<' ';
- foreach(sol[i])
- fout<<*it<<' ';
- }
- fout.close();
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Componente biconexe
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #define foreach(V) for(vector<int>::iterator it=V.begin(),stop=V.end();it!=stop;++it)
- #define foreach_set(V) for(set<int>::iterator it=V.begin(),stop=V.end();it!=stop;++it)
- int n;
- int m;
- vector<int> G[100000+10];
- set<int> sol[100000+10];
- bool viz[100000+10];
- int min_lev[100000+10];
- int init_lev[100000+10];
- int idx=0,nr=0;
- stack<pair<int,int> > st;
- inline void addsol(int x, int y)
- {
- int tmpx=0,tmpy=0;
- while(tmpx!=x || tmpy!=y)
- {
- tmpx=st.top().first;
- tmpy=st.top().second;
- st.pop();
- sol[nr].insert(tmpx);
- sol[nr].insert(tmpy);
- }
- ++nr;
- }
- void df(int nod)
- {
- viz[nod]=true;
- min_lev[nod]=idx;
- init_lev[nod]=idx++;
- foreach(G[nod]) {
- if(!viz[*it]) {
- st.push(make_pair(nod,*it));
- df(*it);
- if(min_lev[*it]>=init_lev[nod]) { //nodul fiu e critic
- addsol(nod,*it);
- }
- min_lev[nod]=min(min_lev[nod],min_lev[*it]);
- } else
- min_lev[nod]=min(min_lev[nod],init_lev[*it]);
- }
- }
- int main()
- {
- for(int i=0; i<m; ++i) {
- int x,y;
- fin>>x>>y;
- G[x].push_back(y);
- G[y].push_back(x);
- }
- for(int i=1; i<=n; ++i)
- if(!viz[i])
- df(i);
- fout<<nr<<'\n';
- for(int i=0;i<nr;++i,fout<<'\n')
- foreach_set(sol[i])
- fout<<*it<<' ';
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Flux maxim
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include <vector>
- using namespace std;
- #define NMAX 1024
- #define pb push_back
- #define sz size()
- #define mp make_pair
- #define INF 0x3f3f3f3f
- int C[NMAX][NMAX];
- int F[NMAX][NMAX];
- int TT[NMAX];
- vector<int> G[NMAX];
- int N, M;
- int cd[NMAX];
- int viz[NMAX];
- int BF()
- {
- int i, j, nod, V;
- cd[0] = 1;
- cd[1] = 1;
- memset(viz, 0, sizeof(viz));
- viz[1] = 1;
- for (i = 1; i <= cd[0]; i++)
- {
- nod = cd[i];
- if (nod == N) continue;
- for (j = 0; j < G[nod].sz; j++)
- {
- V = G[nod][j];
- if (C[nod][V] == F[nod][V] || viz[V]) continue;
- viz[V] = 1;
- cd[ ++cd[0] ] = V;
- TT[V] = nod;
- }
- }
- return viz[N];
- }
- int main()
- {
- freopen("maxflow.in", "r", stdin);
- freopen("maxflow.out", "w", stdout);
- int i, flow, fmin, x, y, z, nod;
- scanf("%d %d ", &N, &M);
- for (i = 1; i <= M; i++)
- {
- scanf("%d %d %d ", &x, &y, &z);
- C[x][y] += z;
- G[x].pb(y);
- G[y].pb(x);
- }
- for (flow = 0; BF();)
- for (i = 0; i < G[N].sz; i++)
- {
- nod = G[N][i];
- if (F[nod][N] == C[nod][N] || !viz[nod]) continue;
- TT[N] = nod;
- fmin = INF;
- for (nod = N; nod != 1; nod = TT[nod])
- fmin = min(fmin, C[ TT[nod] ][nod] - F[ TT[nod] ][nod]);
- if (fmin == 0) continue;
- for (nod = N; nod != 1; nod = TT[nod])
- {
- F[ TT[nod] ][nod] += fmin;
- F[nod][ TT[nod] ] -= fmin;
- }
- flow += fmin;
- }
- printf("%d ", flow);
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Cuplaj maxim in graf bipartit
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <cstdio>
- #include <vector>
- #include <algorithm>
- using namespace std;
- const char iname[] = "cuplaj.in";
- const char oname[] = "cuplaj.out";
- #define MAXN 10005
- #define FOR(i, a, b) for (int i = (int)(a); i <= (int)(b); ++ i)
- #define FORI(i, V) for (vector <int>::iterator i = (V).begin(); i != (V).end(); ++ i)
- vector <int> G[MAXN];
- int l[MAXN], r[MAXN], u[MAXN];
- int pairup(const int n)
- {
- if (u[n]) return 0;
- u[n] = 1;
- FORI (i, G[n]) if (!r[*i]) {
- l[n] = *i;
- r[*i] = n;
- return 1;
- }
- FORI (i, G[n]) if (pairup(r[*i])) {
- l[n] = *i;
- r[*i] = n;
- return 1;
- }
- return 0;
- }
- int main(void)
- {
- freopen(iname, "r", stdin);
- freopen(oname, "w", stdout);
- int n, m, cnt_edges;
- scanf("%d %d %d", &n, &m, &cnt_edges);
- for (; cnt_edges --; )
- {
- int x, y;
- scanf("%d %d", &x, &y);
- G[x].push_back(y);
- }
- for (int change = 1; change; )
- {
- change = 0;
- memset(u, 0, sizeof(u));
- FOR (i, 1, n) if (!l[i])
- change |= pairup(i);
- }
- int cuplaj = 0;
- FOR (i, 1, n) cuplaj += (l[i] > 0);
- printf("%d\n", cuplaj);
- FOR (i, 1, n) if (l[i] > 0)
- printf("%d %d\n", i, l[i]);
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Flux maxim de cost minim
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include <assert.h>
- #include <vector>
- using namespace std;
- #define maxn 360
- #define inf 2000000000
- #define ll long long
- int N, M, S, D;
- int Drum, L, Sum;
- vector <int> A[maxn];
- int G[maxn];
- int Dist[maxn], From[maxn], Pot[maxn];
- int H[maxn], P[maxn];
- int C[maxn][maxn], F[maxn][maxn], Cost[maxn][maxn];
- void push(int x)
- {
- int aux;
- while (x/2>1 && Dist[H[x]]<Dist[H[x/2]])
- {
- aux = H[x], H[x] = H[x/2], H[x/2] = aux;
- P[H[x]] = x;
- P[H[x/2]] = x/2;
- x /= 2;
- }
- }
- void pop(int x)
- {
- int y = 0, aux;
- while (x != y)
- {
- y = x;
- if (y*2<=L && Dist[H[x]]>Dist[H[y*2]]) x = y*2;
- if (y*2+1 <= L && Dist[H[x]]>Dist[H[y*2+1]]) x = y*2+1;
- aux = H[x], H[x] = H[y], H[y] = aux;
- P[H[x]] = x;
- P[H[y]] = y;
- }
- }
- int BellmanFord()
- {
- int i, stop = 0, j, k;
- for (i = 1; i <= N; i++) Dist[i] = inf;
- Dist[S] = 0;
- for (i = 1; i <= N && !stop; i++)
- {
- stop = 1;
- for (j = 1; j <= N; j++)
- for (k = 0; k < G[j]; k++)
- if (C[j][A[j][k]]-F[j][A[j][k]]>0 && Dist[j]+Cost[j][A[j][k]]<Dist[A[j][k]])
- {
- stop = 0;
- Dist[A[j][k]] = Dist[j] + Cost[j][A[j][k]];
- }
- }
- Sum = Dist[D];
- return stop;
- }
- int Dijkstra()
- {
- int i, j;
- // Fac transformarea astfel incat sa am doar costuri pozitive pe arcele active (cele cu capacitate > flux)
- for (i = 1; i <= N; i++)
- for (j = 0; j < G[i]; j++)
- if (Dist[i] != inf && Dist[A[i][j]] != inf) Cost[i][A[i][j]] += Dist[i] - Dist[A[i][j]];
- // Initializari
- for (i = 1; i <= N; i++)
- {
- Dist[i] = inf;
- H[i] = i;
- P[i] = i;
- From[i] = -1;
- }
- // Fac Dijkstra
- Dist[S] = 0;
- H[1] = S, H[S] = 1;
- P[1] = S, P[S] = 1;
- L = N;
- while (L>1 && Dist[H[1]] != inf)
- {
- for (i = 0; i < G[H[1]]; i++)
- {
- int v = A[H[1]][i];
- if (C[H[1]][v]-F[H[1]][v]>0) assert(Cost[H[1]][v]>=0); // Verific daca am arce cu cost negativ active
- if (C[H[1]][v]-F[H[1]][v]>0 && Dist[H[1]]+Cost[H[1]][v]<Dist[v])
- {
- Dist[v] = Dist[H[1]] + Cost[H[1]][v];
- From[v] = H[1];
- push(P[v]);
- }
- }
- H[1] = H[L--];
- P[H[1]] = 1;
- if (L > 1) pop(1);
- }
- // Daca am gasit drum, cresc fluxul pe el
- if (Dist[D] != inf)
- {
- int Vmin = inf;
- Drum = 1;
- for (i = D; i != S; i = From[i])
- Vmin = min(Vmin, C[From[i]][i] - F[From[i]][i]);
- for (i = D; i != S; i = From[i])
- {
- F[From[i]][i] += Vmin;
- F[i][From[i]] -= Vmin;
- }
- Sum += Dist[D];
- return Vmin * Sum;
- }
- return 0;
- }
- ll Flux()
- {
- ll Rez = 0;
- Drum = 1;
- // Cat timp mai exista un drum valabil, bag flux
- while (Drum)
- {
- Drum = 0;
- Rez += Dijkstra();
- }
- return Rez;
- }
- int main()
- {
- freopen("fmcm.in", "r", stdin);
- freopen("fmcm.out", "w", stdout);
- int i, x, y, z, cap;
- // Citesc graful
- scanf("%d %d %d %d ", &N, &M, &S, &D);
- for (i = 1; i <= M; i++)
- {
- scanf("%d %d %d %d ", &x, &y, &cap, &z);
- A[x].push_back(y);
- A[y].push_back(x);
- C[x][y] = cap;
- Cost[x][y] = z;
- Cost[y][x] = -z;
- }
- for (i = 1; i <= N; i++) G[i] = A[i].size();
- // Fac primul Bellman-Ford, cand inca am costuri negative
- assert(BellmanFord());
- // Calculez fluxul maxim de cost minim
- printf("%lld\n", Flux());
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Cuplaj maxim de cost minim
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include <vector>
- #include <string.h>
- using namespace std;
- #define MAX_N 710
- #define inf 2000000000
- #define pb push_back
- int n, m, e, dest, sol, nr, improve;
- int Q[MAX_N * MAX_N], tata[MAX_N], dist[MAX_N], use[MAX_N];
- int C[MAX_N][MAX_N], F[MAX_N][MAX_N], edge[MAX_N][MAX_N];
- vector <int> v[MAX_N], cost[MAX_N];
- void cit() {
- scanf("%d %d %d", &n, &m, &e);
- for (int i = 1; i <= e; i++) {
- int p, q, val;
- scanf("%d %d %d", &p, &q, &val);
- p++; q += n + 1;
- v[p].pb(q); cost[p].pb(val);
- v[q].pb(p); cost[q].pb(-val);
- edge[p][q] = i;
- C[p][q] = 1;
- }
- }
- void build_graph() {
- //sursa este nodul 1, destinatia n + m + 2
- dest = n + m + 2;
- for (int i = 2; i <= n + 1; i++) {
- v[1].pb(i); cost[1].pb(0);
- v[i].pb(1); cost[i].pb(0);
- C[1][i] = 1;
- }
- for (int i = n + 2; i <= n + m + 1; i++) {
- v[i].pb(dest); cost[i].pb(0);
- v[dest].pb(i); cost[dest].pb(0);
- C[i][dest] = 1;
- }
- }
- int bellman_ford() {
- for (int i = 1; i <= dest; i++) {
- dist[i] = inf;
- tata[i] = -1;
- use[i] = 0;
- }
- dist[1] = 0; use[1] = 1;
- int st = 0, dr = 1; Q[1] = 1;
- while (st < dr) {
- st++;
- int len = v[Q[st]].size();
- for (int i = 0; i < len; i++) {
- if (C[Q[st]][v[Q[st]][i]] > F[Q[st]][v[Q[st]][i]] && dist[v[Q[st]][i]] > dist[Q[st]] + cost[Q[st]][i]) {
- dist[v[Q[st]][i]] = dist[Q[st]] + cost[Q[st]][i];
- tata[v[Q[st]][i]] = Q[st];
- if (!use[v[Q[st]][i]]) {
- Q[++dr] = v[Q[st]][i];
- use[v[Q[st]][i]] = 1;
- }
- }
- }
- use[Q[st]] = 0;
- }
- if (dist[dest] < inf) {
- int flux = inf;
- for (int i = dest; i != 1; i = tata[i])
- flux = min(flux, C[tata[i]][i] - F[tata[i]][i]);
- for (int i = dest; i != 1; i = tata[i]) {
- F[tata[i]][i] += flux;
- F[i][tata[i]] -= flux;
- }
- return flux * dist[dest];
- }
- return 0;
- }
- void solve() {
- //construiesc graful de flux
- build_graph();
- improve = 1;
- while (improve) {
- improve = bellman_ford();
- sol += improve;
- }
- }
- void write() {
- for (int i = 2; i <= n + 1; i++)
- for (int j = n + 2; j < dest; j++)
- if (C[i][j] && F[i][j]) {
- nr++;
- break;
- }
- printf("%d %d\n", nr, sol);
- for (int i = 2; i <= n + 1; i++)
- for (int j = n + 2; j < dest; j++)
- if (C[i][j] && F[i][j]) {
- printf("%d ", edge[i][j]);
- break;
- }
- printf("\n");
- }
- int main() {
- freopen("cmcm.in", "r", stdin);
- freopen("cmcm.out", "w", stdout);
- cit();
- solve();
- write();
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Problema rucsacului
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- // Problema rucsacului, dinamica O(N*G) timp, O(N) memorie
- #include <cstdio>
- #include <algorithm>
- using namespace std;
- #define MAXN 5010
- #define MAXG 10010
- int N, G, Pmax;
- int W[MAXN], P[MAXN];
- int D[2][MAXG];
- int main()
- {
- freopen("rucsac.in", "r", stdin);
- freopen("rucsac.out", "w", stdout);
- // Citire
- scanf("%d%d", &N, &G);
- for(int i = 1; i <= N; ++i)
- scanf("%d%d", &W[i], &P[i]);
- // Dinamica D[i][cw] - profitul maxim pe care-l putem obtine adaugand o submultime a primelor i obiecte, insumand greutatea cw
- // Din aceasta dinamica vom tine ultimele doua linii, astfel: linia l va fi cea pe care avem solutia pentru al (i-1)-lea element,
- // in timp ce pe linia 1-l vom construi solutia pentru elementul i.
- int l=0;
- for(int i = 1; i <= N; ++i, l = 1 - l)
- for(int cw = 0; cw <= G; ++cw)
- {
- // Mai intai nu punem obiectul i.
- D[1-l][cw] = D[l][cw];
- // Daca acest lucru duce la o solutie curenta mai buna, adaugam obiectul i la o solutie anterioara.
- if(W[i] <= cw)
- D[1-l][cw] = max(D[1-l][cw], D[l][cw - W[i]] + P[i]);
- }
- // Solutia se va afla in statea D[N][G], adica pe linia l, la coloana G
- Pmax = D[l][G];
- // Afisare
- printf("%d\n", Pmax);
- return 0;
- }
- //////////////////////////////////////////////////////////////
- Problema rucsacului -- faster (descrescator)
- //////////////////////////////////////////////////////////////
- // Infoarena - Arhiva Educationala rucsac
- // Februrie 2012 Marius Dumitran
- // Programare dinamica clasica timp O(N*G) memorie O(G)
- #include<string.h>
- #include<stdio.h>
- #include<vector>
- #include<algorithm>
- #define maxn 5001
- #define maxg 10001
- using namespace std;
- int W[maxn], P[maxn];
- int Optim[maxg];
- int main() {
- freopen("rucsac.in", "r", stdin);
- freopen("rucsac.out", "w", stdout);
- int N, G;
- scanf("%d %d", &N, &G);
- for (int i = 1; i <= N; ++i) {
- scanf("%d %d", &W[i], &P[i]);
- }
- Optim[0] = 0;
- int sol = 0;
- for( int i = 1; i <= N; ++i)
- for( int j = G - W[i]; j >= 0; --j) {
- if( Optim[j+W[i]] < Optim[j] + P[i] )
- {
- Optim[j+W[i]] = Optim[j] + P[i];
- if( Optim[j+W[i]] > sol)
- sol = Optim[j+W[i]];
- }
- }
- printf("%d", sol);
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- pscpld - palindrom in O(N)
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- typedef long long int64;
- const int MAX_N = 1000005;
- int n;
- char v[2 * MAX_N];
- int d[2 * MAX_N];
- void read() {
- assert(freopen("pscpld.in", "r", stdin));
- assert(freopen("pscpld.out", "w", stdout));
- scanf("%s", v + 1);
- n = strlen(v + 1);
- for (int i = 2 * n + 1; i > 0; --i)
- if ((i % 2) == 1)
- v[i] = '#';
- else
- v[i] = v[i / 2];
- n = 2 * n + 1;
- }
- void solve() {
- int best = 0;
- for (int i = 1; i <= n; ++i) {
- if (best + d[best] >= i)
- d[i] = min(best + d[best] - i, d[best - (i-best)]);
- while (i - d[i] - 1 > 0 && i + d[i] + 1 <= n &&
- v[i - d[i] - 1] == v[i + d[i] + 1])
- ++d[i];
- if (i + d[i] >= best + d[best])
- best = i;
- }
- int64 sol = 0;
- for (int i = 1; i <= n; ++i)
- if ((i % 2) == 1)
- sol += d[i] / 2;
- else
- sol += (d[i] + 1) / 2;
- printf("%lld\n", sol);
- }
- int main() {
- read();
- solve();
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- Eliminarea gaussiana
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- /*
- Eliminarea Gaussiana este cel mai folosit algoritm pentru rezolvarea sistemelor de ecuatii liniare. Metoda reduce succesiv ecuatiile, lasand matricea initiala sub o forma din care vom putea afla usor valorile necunoscutelor. Astfel, notand cu pi pozitia celui mai din stanga coeficient nenul de pe linia i, algoritmul garanteaza obtinerea urmatoarului sir de relatii: p1 < p2 < ... < pN (1). Aceste pozitii vor fi chiar indicii necunoscutelor fixe, cele care pot lua o singura valoare pentru ca sistemul sa aiba in continuare solutie. Celelalte necunoscute, ale caror indici nu se regasesc printre aceste pozitii, pot lua orice valoare si se numesc variabile libere. Pentru a usura calculele, vom considera in continuare ca acestea iau valoarea 0.
- In continuare vom descrie algoritmul propriu-zis. Pornim cu un indice pentru linii, sa-l notam i, si un indice pentru coloane, j, initializate initial cu 1. Cautam pe coloana j, o linie x, i ≤ x astfel incat Ax,j ≠ 0. Daca aceasta linie nu exista, inseamna ca necunoscuta cu indicele j este variabila libera, iar noi incrementam indicele j. Altfel, interschimbam liniile i si x si impartim toata ecuatia de pe linia i la Ai,j, pentru a face coeficientul Ai,j egal cu 1, usurand calculele urmatoare. In continuare vom scadea, din toate ecuatiile u, i < u, ecuatia i inmultita cu o valoare zu, astfel incat toti coeficientii Au,j sa devina 0. Avem astfel Au,j - zu * Ai,j = 0 => zu = Au,j / Ai,j, dar cum Ai,j = 1, zu = Au,j. Aceasta reducere este necesara pentru respectarea conditiei (1), avand in vedere ca nu putem avea x ≠ i cu px = pi. Incrementam pe i si j si reluam procedeul de la inceput. Algoritmul se incheie cand i > N sau j > M. Complexitatea acestuia este O(N3) ca timp si O(N2) ca memorie.
- Acum matricea respecta relatia (1) si putem incepe sa calculam valorile necunoscutelor. Luam ecuatiile in ordine de la N spre 1, gasim pozitia pi, iar xpi va fi dat de relatia xpi = Ai,M+1 - Ai,M * xM - Ai,M-1 * xM-1 - ... - Ai,pi+1 * xpi+1. Relatia (1) ne garanteaza ca xpi+1, xpi+2, ... , xM vor fi calculate anterior. Daca pe parcurs gasim o linie de forma (0, 0, 0, ... , 0, X) (doar rezultatul ecuatiei este nenul), sistemul nu are solutie.
- O implementare de 100 de puncte gasiti aici. Acest algoritm poate fi aplicat cu succes pentru sisteme de ecuatii in care coeficientii, necunoscutele si rezultatele sunt doar 0 si 1, iar operatorul + din ecuatii este inlocuit de XOR.
- */
- #include <cstdio>
- using namespace std;
- #define MAXN 310
- #define EPS 0.0000001
- int N, M;
- double A[MAXN][MAXN];
- double X[MAXN];
- int main()
- {
- freopen("gauss.in", "r", stdin);
- freopen("gauss.out", "w", stdout);
- //Citire
- scanf("%d%d", &N, &M);
- for(int i = 1; i <= N; ++i)
- for(int j = 1; j <= M+1; ++j)
- scanf("%lf", &A[i][j]);
- int i = 1, j = 1, k;
- double aux;
- //Algoritmul lui Gauss propriu-zis
- while(i <= N && j <= M)
- {
- //Cautam o linie k pentru care A[k][j] sa fie nenul. Folosim epsilonul pentru a nu lua in considerare micile erori de calcul.
- for(k = i; k <= N; ++k)
- if(A[k][j]<-EPS || A[k][j]>EPS)
- break;
- //Daca nu gasim linia, necunoscuta j este variabila libera, incrementam pe j si trecem la pasul urmator.
- if(k == N+1)
- {
- ++j;
- continue;
- }
- //Interschimbam pe k cu i, daca este cazul.
- if(k != i)
- for(int l = 1; l <= M+1; ++l)
- {
- aux = A[i][l];
- A[i][l] = A[k][l];
- A[k][l] = aux;
- }
- //Pentru a usura calculele, impartim toate valorile de pe linia i la A[i][j], A[i][j] devenind 1.
- //Observam ca valorile de pe linia i si coloanele 1..j-1 sunt egale cu 0 de la pasii precedenti ai algoritmului,
- //deci nu e necesar sa le parcurgem pentru a le imparti.
- for(int l = j+1; l <= M+1; ++l)
- A[i][l] = A[i][l] / A[i][j];
- A[i][j] = 1;
- //Scadem din ecuatiile i+1...N ecuatia i inmultita cu A[u][j], pentru a egala toti coeficientii de coloana j
- //a acestor linii la 0.
- for(int u = i+1; u <= N; ++u)
- {
- for(int l = j+1; l <= M+1; ++l)
- A[u][l] -= A[u][j] * A[i][l];
- A[u][j] = 0;
- }
- ++i; ++j;
- }
- //Calculul necunoscutelor
- for(int i = N; i>0; --i)
- for(int j = 1; j <= M+1; ++j)
- if(A[i][j]>EPS || A[i][j]<-EPS)
- {
- //Singura valoare nenegativa de pe linia i este rezultatul => sistemul nu are solutie.
- if(j == M+1)
- {
- printf("Imposibil\n");
- return 0;
- }
- //Calculam pe necunoscuta j = rezultatul ecuatiei i - necunoscutele j+1...M inmultite cu coeficientii lor din aceasta ecuatie.
- X[j] = A[i][M+1];
- for(int k = j+1; k <= M; ++k)
- X[j] -= X[k] * A[i][k];
- break;
- }
- //Afisare
- for(int i = 1; i <= M; ++i)
- printf("%.8lf ", X[i]);
- printf("\n");
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- // Trie
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <cstdio>
- #include <cstring>
- #define CH (*s - 'a')
- using namespace std;
- struct Trie {
- int cnt, nrfii;
- Trie *fiu[ 26 ];
- Trie() {
- cnt = nrfii = 0;
- memset( fiu, 0, sizeof( fiu ) );
- }
- };
- Trie *T = new Trie;
- void ins( Trie *nod, char *s ) {
- if( *s == '\n' ) {
- nod->cnt ++; return;
- }
- if( nod->fiu[ CH ] == 0 ) {
- nod->fiu[ CH ] = new Trie;
- nod->nrfii ++;
- }
- ins( nod->fiu[ CH ], s+1 );
- }
- int del( Trie *nod, char *s ) {
- if( *s == '\n' )
- nod->cnt --;
- else if( del( nod->fiu[ CH ], s+1 ) ) {
- nod->fiu[ CH ] = 0;
- nod->nrfii --;
- }
- if( nod->cnt == 0 && nod->nrfii == 0 && nod != T ) {
- delete nod; return 1;
- }
- return 0;
- }
- int que( Trie *nod, char *s ) {
- if( *s == '\n' )
- return nod->cnt;
- if( nod->fiu[ CH ] )
- return que( nod->fiu[ CH ], s+1 );
- return 0;
- }
- int pre( Trie *nod, char *s, int k ) {
- if( *s == '\n' || nod->fiu[ CH ] == 0 )
- return k;
- return pre( nod->fiu[ CH ], s+1, k+1 );
- }
- int main() {
- char line[ 32 ];
- freopen( "trie.in", "r", stdin );
- freopen( "trie.out", "w", stdout );
- fgets( line, 32, stdin );
- while( !feof( stdin ) ) {
- switch( line[0] ) {
- case '0': ins( T, line+2 ); break;
- case '1': del( T, line+2 ); break;
- case '2': printf( "%d\n", que( T, line+2 ) ); break;
- case '3': printf( "%d\n", pre( T, line+2, 0 ) ); break;
- }
- fgets( line, 32, stdin );
- }
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- // Heavy path decomposition
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //Heavy Path Decomposition, O(N * log N * log N)
- #include <cstdio>
- #include <algorithm>
- #include <vector>
- #include <utility>
- using namespace std;
- #define MAXN 100010
- int N, M, nL;
- int v[MAXN], fol[MAXN], niv[MAXN], w[MAXN], l[MAXN];
- int aint[4*MAXN];
- int lTata[MAXN], lNiv[MAXN], lDim[MAXN], lPoz[MAXN];
- vector<int> G[MAXN], P[MAXN];
- pair<int, pair<int, int> > op[MAXN];
- void citire()
- {
- scanf("%d%d", &N, &M);
- for(int i = 1; i <= N; ++i)
- scanf("%d", &v[i]);
- int a, b;
- for(int i = 1; i < N; ++i)
- {
- scanf("%d%d", &a, &b);
- G[a].push_back(b);
- G[b].push_back(a);
- }
- int t, x, y;
- for(int i = 1; i <= M; ++i)
- {
- scanf("%d%d%d", &t, &x, &y);
- op[i] = make_pair(t, make_pair(x, y));
- }
- }
- void df(int nod)
- {
- fol[nod] = 1;
- w[nod] = 1;
- int hN = -1, frunza = 1;
- for(vector<int> :: iterator it = G[nod].begin(); it != G[nod].end(); ++it)
- {
- if(fol[*it])
- continue;
- frunza = 0;
- niv[*it] = niv[nod] + 1;
- df(*it);
- w[nod] += w[*it];
- if(hN == -1)
- hN = *it;
- else
- if(w[hN] < w[*it])
- hN = *it;
- }
- if(frunza)
- {
- l[nod] = ++nL;
- lDim[nL]=1;
- P[nL].push_back(nod);
- return;
- }
- l[nod] = l[hN];
- ++lDim[l[nod]];
- P[l[nod]].push_back(nod);
- for(vector<int> :: iterator it = G[nod].begin(); it != G[nod].end(); ++it)
- {
- if((*it) == hN || niv[*it] < niv[nod])
- continue;
- lTata[l[*it]] = nod;
- lNiv[l[*it]] = niv[nod];
- }
- }
- void build(int nod, int left, int right, int decalaj, int lant)
- {
- if(left == right)
- {
- aint[nod + decalaj] = v[ P[lant][left - 1] ];
- return;
- }
- int med = (left + right) / 2;
- build(nod * 2, left, med, decalaj, lant);
- build(nod * 2 + 1, med+1, right, decalaj, lant);
- aint[nod + decalaj] = max(aint[nod * 2 + decalaj], aint[nod * 2 + 1 + decalaj]);
- }
- void make_paths()
- {
- niv[1] = 1;
- df(1);
- for(int i = 1; i <= nL; ++i)
- {
- reverse(P[i].begin(), P[i].end());
- if(i > 1)
- lPoz[i] = lPoz[i-1] + lDim[i-1] * 4;
- build(1, 1, lDim[i], lPoz[i], i);
- }
- }
- void update(int nod, int left, int right, int poz, int val, int decalaj)
- {
- if(left == right)
- {
- aint[nod + decalaj] = val;
- return;
- }
- int med = (left + right) / 2;
- if(poz<=med)
- update(nod * 2, left, med, poz, val, decalaj);
- else
- update(nod * 2 + 1, med+1, right, poz, val, decalaj);
- aint[nod + decalaj] = max(aint[nod * 2 + decalaj], aint[nod * 2 + 1 + decalaj]);
- }
- int query(int nod, int left, int right, int qleft, int qright, int decalaj)
- {
- if(qleft <= left && right <= qright)
- return aint[nod + decalaj];
- int med = (left + right) / 2, rez = 0;
- if(qleft <= med)
- rez = max(rez, query(nod * 2, left, med, qleft, qright, decalaj) );
- if(med < qright)
- rez = max(rez, query(nod * 2 + 1, med + 1, right, qleft, qright, decalaj) );
- return rez;
- }
- void solve()
- {
- int t, x, y, sol = 0;
- for(int i = 1; i <= M; ++i)
- {
- t = op[i].first; x = op[i].second.first, y = op[i].second.second;
- if(t==0)
- update(1, 1, lDim[l[x]], niv[x] - lNiv[l[x]], y, lPoz[l[x]]);
- else
- {
- sol = 0;
- while(1)
- {
- if(l[x] == l[y])
- {
- if(niv[x] > niv[y])
- swap(x, y);
- sol = max(sol, query(1, 1, lDim[l[x]], niv[x] - lNiv[l[x]], niv[y] - lNiv[l[x]], lPoz[l[x]]) );
- break;
- }
- if(lNiv[l[x]] < lNiv[l[y]])
- swap(x, y);
- sol = max(sol, query(1, 1, lDim[l[x]], 1, niv[x] - lNiv[l[x]], lPoz[l[x]]) );
- x = lTata[l[x]];
- }
- printf("%d\n", sol);
- }
- }
- }
- int main()
- {
- freopen("heavypath.in", "r", stdin);
- freopen("heavypath.out", "w", stdout);
- citire();
- make_paths();
- solve();
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- kinetic parsare smechera / rapida
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- using namespace std;
- char *buffer;
- int AINT[1<<15];
- void read(int &a)
- {
- a&=0;
- char semn = 1;
- while((*buffer < '0' || *buffer > '9') && *buffer != '-')
- ++buffer;
- if(*buffer == '-')
- semn = -1,++buffer;
- while(*buffer >='0' && *buffer <= '9')
- a = a * 10 + *(buffer++) - 48;
- a*=semn;
- }
- int a[550],b[550];
- int last_t;
- int n,m;
- inline int query(const int &x,const int &y,const int &t)
- {
- int i;
- int ret=0;
- for(i=1;i<=n;++i)
- {
- if(a[i] + b[i]*t <= y && a[i]+b[i]*t >= x)
- ++ret;
- }
- return ret;
- }
- void swap(int &a,int &b)
- {
- a ^=b;
- b ^=a;
- a ^=b;
- }
- int main()
- {
- freopen("kinetic.in","r",stdin);
- freopen("kinetic.out","w",stdout);
- fseek(stdin,0,SEEK_END);
- int len = ftell(stdin);
- int i,j;
- int x,y,t;
- buffer = new char[len];
- rewind(stdin);
- fread(buffer,1,len,stdin);
- read(n);
- read(m);
- for(i=1;i<=n;++i)
- {
- read(a[i]);
- read(b[i]);
- }
- for(i=1;i<=m;++i)
- {
- read(x);
- read(y);
- read(t);
- if(x > y)
- swap(x,y);
- printf("%d\n",query(x,y,t));
- }
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- scanare fisiere ok evaluator cheat
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #define nrlines 2
- void uhyifbe(char *yhuiindu){for(char *yhujindu=yhuiindu+1;*yhujindu!=0;yhujindu+=2){*yhuiindu++=*yhujindu;}*yhuiindu='\0';}
- int main()
- {
- int j;
- ifstream ui;
- ///retine date fin
- string s2[nrlines];
- for(j=0;j<nrlines;++j){
- getline(fin,j[s2]);
- // cerr<<s2[j]<<'\n';
- }
- fin.close();
- for(int testnr=0;testnr<40;++testnr){
- string s;
- int oldtest=testnr;
- if(testnr<=10) testnr=10-testnr;
- ostringstream ss;
- ss<<testnr;
- string ys;
- char ps[] = "\001C\002:\003/\004E\005v\001a\002l\003_\004O\005J\001I\002_\0032\0040\0051\0013\002_\003X\004I\005_\001X\002I\003I\004/\005p\001r\002o\003b\004l\005e\001m\002e\003/\000\000";uhyifbe(ps);
- ys.append(ps);
- ys.append(nume);
- char dasjk[] = "\001/\002t\003e\004s\005t\001e\002/\000\000";uhyifbe(dasjk);
- ys.append(dasjk);
- ys.append(ss.str());
- ys.append("-"nume".in");
- ui.open(ys.c_str());
- ///compara date din ui cu date din fin
- for(j=0;j<nrlines;++j){
- getline(ui,s);
- if(s!=s2[j]) break;
- }
- ui.close();
- if(j==nrlines)///ok, afiseaza/retine
- {
- ys="";
- char kjhb[] = "\001C\002:\003/\004E\005v\001a\002l\003_\004O\005J\001I\002_\0032\0040\0051\0013\002_\003X\004I\005_\001X\002I\003I\004/\005p\001r\002o\003b\004l\005e\001m\002e\003/\000\000";uhyifbe(kjhb);
- ys.append(kjhb);
- ys.append(nume);
- char dasjk[] = "\001/\002t\003e\004s\005t\001e\002/\000\000";uhyifbe(dasjk);
- ys.append(dasjk);
- ys.append(ss.str());
- ys.append("-"nume);
- char dasps[] = "\001.\002o\003k\000";uhyifbe(dasps);
- ys.append(dasps);
- ui.open(ys.c_str());
- for(j=0;j<nrlines;++j){///afiseaza/retine
- getline(ui,s);
- fout<<s<<'\n';
- }
- ui.close();
- break;
- }
- if(oldtest<=10)
- testnr=oldtest;
- }
- return 0;
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- generator teste
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- ofstream fout(nume);
- const int MAXN=5000;
- const int MAXM=100000;
- srand(time(0));
- n=rand()%MAXN+1;
- m=rand()%MAXM+1;
- fout<<n<<' '<<m<<'\n';
- vector<int> v(n);
- for(int i=0;i<v.size();++i) v[i]=i+1;
- random_shuffle(v.begin(),v.end());
- foreach(it,v) fout<<*it<<' ';
- fout<<'\n';
- for(int i=0;i<m;++i){
- int x=rand()%n;
- int y=rand()%n;
- while(v[x]>v[y]){
- y=rand()%n;
- }
- fout<<v[x]<<' '<<v[y]<<'\n';
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- evaluator budau
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- #include <iostream>
- #include <fstream>
- #include <vector>
- #include <cassert>
- #include <cstdlib>
- #include <ctime>
- #include <algorithm>
- using namespace std;
- void gen(int N, int M) {
- ofstream in("inversiuni.in");
- in << N << " " << M << "\n";
- vector<int> V(N);
- for (int i = 0; i < N; ++i)
- V[i] = i + 1;
- random_shuffle(V.begin(), V.end());
- for (int i = 0; i < N; ++i)
- in << V[i] << " ";
- in << "\n";
- for (int i = 0; i < M; ++i) {
- int x = rand() % N + 1;
- int y = rand() % N + 1;
- if (x > y)
- swap(x, y);
- in << x << " " << y << "\n";
- }
- }
- vector<int> eval(const char *S) {
- assert(system(S) == 0);
- vector<int> result;
- ifstream out("inversiuni.out");
- int x;
- while (out >> x)
- result.push_back(x);
- return result;
- }
- int main() {
- srand(time(NULL));
- int TESTS, MAXN, MAXM;
- cout << "TESTS = "; cin >> TESTS;
- cout << "MAXN = "; cin >> MAXN;
- cout << "MAXM = "; cin >> MAXM;
- for (int i = 1; i <= TESTS; ++i) {
- if (i == TESTS)
- gen(MAXN, MAXM);
- else
- gen(rand() % MAXN + 1, rand() % (MAXM + 1));
- vector<int> main = eval("./main");
- vector<int> brut = eval("./brut");
- cout << "Case #" << i << ": ";
- if (main != brut) {
- cout << "Wrong! \n";
- return 0;
- }
- cout << "OK!\n";
- }
- }
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////
- ´^/c/io/fscanf.htmÁoŽ/c/io/fseek.htmÏ~’P/c/io/fsetpos.htmâN‹C/c/io/ftell.htmî‰j/c/io/fwrite.htm÷{"/c/io/getc.htm‘…”t/c/io/getchar.htm‘šŠR/c/io/gets.htm‘¤c-/c/io/perror.htm‘²”|/c/io/printf.htm‘ÇÃx/c/io/putc.htm’‹—
- /io/flags.htm§Òs‰\
- /io/flush.htm§ÜO‹d/io/gcount.htm§è3‰D/io/get.htm§ñwa/io/getline.htm¨XŸ
- /io/good.htm¨®e/io/ignore.htm¨½}/io/io_flags.htm¨Íè/io/open.htm©µ6’M/io/peek.htm©È‰a/io/precision.htm©Ñd(/io/put.htm©á‰?/io/putback.htm©êK‰U/io/rdstate.htm©ô Š/io/read.htm©þ(”K
- /io/seekg.htmª’s‹n
- /io/seekp.htmªža‹
- /io/setf.htmª©k™A/io/sstream/ /io/sstream/constructors.htmªÃ, !/io/sstream/operators.htmªãMŒ?/io/sstream/rdbuf.htmªð‰/io/sstream/start.htmªù“/io/sstream/str.htm«ž1
- /io/start.htm««J¶G/io/sync_with_stdio.htm«â‰r
- /io/tellg.htm«ì‰3
- /io/tellp.htm«õ6•U/io/unsetf.htm¬‹‰
- /io/width.htm¬”
- /io/write.htm¬£.Š-
- ¬W÷ ~@Œ•S;ía±{7Òß«ÖýƒM#k´ï¨dý™+Ò«©w=UÒŠM+Åø°X`3>¥Ã yhÑvÐ9ñnVâ†Mçª"Ø%?z/:1ˆ<êÊkÓ
- ^íZÓ«rAÄcœGy_±à:Šø7
- ª)ÖŒ€ëÀÏ„&Àn
- $ܶÖÀï*©h~iB/0ã5çü½Ë[
- ±5ÇÅóÃÿdq2ÚR.8važ·øQkYa õ”}«Z>½5¥ä9—´ˆý2*ƒ†°Ê5Œ§w}3áÎÉÓKï¬ÑÄva† ù½®™]°0`óØW,ß@÷èK…f™
- ¾3U®ˆIô©Ò…#òÖ8Al/O¶q“íFŽ 3ßÊzw£öätÊ"¾pÍd—Å/Sk8SV÷Z\¾wvÚâ£^ðÕÄU´¬ÎÓiÃí» £3XÏãÿO,pEå˜ñ@üD„‘6xèÓ££bãÞò´Z}¿·í7!ÛdFöÈFxˆK
- ‡î æ½€ðKï-1“Np¹å˜TåäÝø½Àø.¨IŸ$U©RÒ >ÓsùÛôñÐz‡/õSCv¡pÕ[Piªw žjaÄS,Î.L‹Þzã~*(®à˜`µ[³ä§?’cÉáØ÷+ÙGéS²óÓ„ÚÑúÙ O›•©Øq‡þ"ÉVn…ïGáö€æcg„…
- uiìµ_öŒä×`HøõGk(VÊTKN©¿EXa„ẂîÒð+BÆšxI"^w PHÞQmè‘[I²ôÁ½6¬¼t4v+á>h4ÏàRëKh葱JÏ#ÿZâ~
- )¶×àÖÊ9㙯Z¿|-XŽKšù{§#_×ÄL<vŽIºE”WylèŸÔ"À]Ã_Ð!•KžšT
- Z:ß
- j*þsŽ
- ë5×"zòsnˆ|g(‹sV :‚¹“+>PÒÉî+’æÁ~¼]•ù¥|ác¦õÖ
- ¯•" q^ì´ž„ýÆœ2E<iÚüÄØÙ wuþÍ÷÷$ÄvË{ÁÝèÐKÙ>åš=YN&ƒ]¶Ñp'"ÃØÑœð] Öɇë%ø:EÏcÅP¾¹EZ[nÖ(‹ï „\¤ `]—:Ó}}@¡÷ã/?/œ)r¶
- «JË´ð_þD,pß^¬;áÞ1ÏpË¡iÎŽªâ~Õ.çf³¬ÔA«KçŽæ.ÙN'bfàž®Žõ%«é¢@kOp]-½#‘%Ƚ€\Æ…™4û˜Ô“NæOF®‹ÉùùÀ²,V¯ýù¥5Hú5ÃLõŒó}H~Ÿ©¶(¯É·w-¬¹úãÕ0@î×9[€Ú—…Ó*å§.ÌÐ Z/탯X]Ro\æ
- ê^´-}íBÐÑi¼*ø\ áÀDZŸNO'¡š³TéóÚDz`ÖA‰I”
- ¸îxø£Â{s—¨s ë'íGcjÆ'ÆK"€Ùãe5fƒ¹RÀ”-ÂóÏǸÙGã"zr¢‹R ¸ª“œ£³.[fz›?ˆõÆÂ#b
- ÿÓ;×uÁØÍ©£šx}ŒJ÷¯ÎÇ9Íûø^Õ{ßÊí9Æ+õs•g>)ì~‡3ÈèM
- k`Eå3r~u¸9þÉ3Ô4½ÏVÜ#ÓÿGÉØ£¼<WYsà’?yk‘ŠgÈÎcÌ
Add Comment
Please, Sign In to add comment