├── .gitignore ├── 00_fp ├── first-prg.png ├── fp-ce-expl.png ├── fp-ce.png ├── fp-quick-start.tex ├── fpc-0.png ├── fpc-noname.png ├── output-1.png └── output-3.png ├── 01_backtrack ├── 01_backtrack.tex ├── 01_backtrack_main.tex ├── do.sh ├── do_main.sh ├── problems.cls └── texts │ ├── 01_1_elementary.tex │ ├── 01_1_elementary │ └── tree.mp │ ├── 01_2_cuts.tex │ ├── 01_3_heur.tex │ └── 01_4_add.tex ├── 02_complexity ├── 02_complexity.tex ├── 02_complexity_main.tex ├── do.sh └── problems.cls ├── 03_shortideas ├── 03_shortideas.tex ├── 03_shortideas_main.tex ├── do.sh ├── encodings.pas ├── graphics.cfg ├── ideas │ ├── 03_10_GCDnodiv.tex │ ├── 03_11_quicksearch.tex │ ├── 03_12_noinitarray.tex │ ├── 03_13_period.tex │ ├── 03_13_period │ │ └── rho.eps │ ├── 03_14_names.tex │ ├── 03_1_encodings.tex │ ├── 03_1_encodings │ │ ├── dos.bmp │ │ ├── dos.eps │ │ ├── dos.png │ │ ├── koi.bmp │ │ ├── koi.png │ │ ├── rustext_dos.bmp │ │ ├── rustext_dos.png │ │ ├── rustext_koi.bmp │ │ ├── rustext_koi.png │ │ ├── rustext_utf16.bmp │ │ ├── rustext_utf16.png │ │ ├── rustext_utf8.bmp │ │ ├── rustext_utf8.png │ │ ├── rustext_win.bmp │ │ ├── rustext_win.png │ │ ├── utf8_contact.bmp │ │ ├── utf8_contact.png │ │ ├── win.bmp │ │ └── win.png │ ├── 03_2_Axor32.tex │ ├── 03_3_types.tex │ ├── 03_4_compswitches.tex │ ├── 03_5_bitandor.tex │ ├── 03_6_fileof.tex │ ├── 03_7_optimes.tex │ ├── 03_8_changetest.tex │ └── 03_9_quickpow.tex └── problems.cls ├── 04_dfs ├── 04_dfs.tex ├── 04_dfs_main.tex ├── do.sh ├── graphics.cfg ├── problems.cls └── texts │ ├── 04_0_intro.tex │ ├── 04_1_dfs.tex │ ├── 04_1_dfs │ └── graph.mp │ ├── 04_2_simple.tex │ ├── 04_2_simple │ └── graph.mp │ ├── 04_3_topsort.tex │ ├── 04_3_topsort │ └── graph.mp │ ├── 04_4_bridges.tex │ ├── 04_4_bridges │ └── conj.mp │ ├── 04_5_problems.tex │ ├── 04_6_hints.tex │ └── 04_7_answers.tex ├── 05_dynprog ├── 05_dynprog.tex ├── 05_dynprog_main.tex ├── do.sh ├── graphics.cfg ├── problems.cls ├── problems_ans.cls └── texts │ ├── 05_1_elementary.tex │ ├── 05_2_fundamental.tex │ ├── 05_2_fundamental │ ├── graph.mp │ ├── mptextmp.mp │ └── tree.mp │ ├── 05_3_howtogetanswer.tex │ ├── 05_4_classes.tex │ ├── 05_5_ways.tex │ ├── 05_6_dptypes.tex │ ├── 05_7_tasks.tex │ ├── circle.tex │ └── gencircle.dpr ├── 06_testing ├── 06_testing.tex ├── 06_testing_main.tex ├── a.cpp ├── b.cpp ├── do.sh ├── graphics.cfg └── problems.cls ├── 07_binsearch ├── 07_binsearch.tex ├── 07_binsearch_main.tex ├── do.sh └── problems.cls ├── COPYING.txt ├── README.md ├── _all ├── algoprog.tex ├── do.sh ├── gpl-by-christian-candena-cc-by.eps ├── gpl-by-christian-candena-cc-by.svg ├── gpl-v3-logo.svg ├── license-logos-by-christian-candena-cc-by.svg ├── licensing.tex └── problems.cls ├── conv.sh ├── icheck.sh └── todo.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.bak 3 | 4 | ## tasks and answers 5 | *.ans 6 | *.tsk 7 | *.hnt 8 | *.dup 9 | 10 | # metapost 11 | *.1 12 | *.2 13 | *.3 14 | *.4 15 | *.5 16 | *.6 17 | *.7 18 | *.8 19 | *.9 20 | *.mpx 21 | 22 | ## Core latex/pdflatex auxiliary files: 23 | *.aux 24 | *.lof 25 | *.log 26 | *.lot 27 | *.fls 28 | *.out 29 | *.toc 30 | graphics.cfg 31 | 32 | ## Intermediate documents: 33 | *.dvi 34 | # these rules might exclude image files for figures etc. 35 | *.ps 36 | # *.eps 37 | *.pdf 38 | 39 | ## Bibliography auxiliary files (bibtex/biblatex/biber): 40 | *.bbl 41 | *.bcf 42 | *.blg 43 | *-blx.aux 44 | *-blx.bib 45 | *.run.xml 46 | 47 | ## Build tool auxiliary files: 48 | *.fdb_latexmk 49 | *.synctex.gz 50 | *.synctex.gz(busy) 51 | *.pdfsync 52 | 53 | ## Auxiliary and intermediate files from other packages: 54 | 55 | # algorithms 56 | *.alg 57 | *.loa 58 | 59 | # amsthm 60 | *.thm 61 | 62 | # beamer 63 | *.nav 64 | *.snm 65 | *.vrb 66 | 67 | # glossaries 68 | *.acn 69 | *.acr 70 | *.glg 71 | *.glo 72 | *.gls 73 | 74 | # hyperref 75 | *.brf 76 | 77 | # listings 78 | *.lol 79 | 80 | # makeidx 81 | *.idx 82 | *.ilg 83 | *.ind 84 | *.ist 85 | 86 | # minitoc 87 | *.maf 88 | *.mtc 89 | *.mtc0 90 | 91 | # minted 92 | *.pyg 93 | 94 | # nomencl 95 | *.nlo 96 | 97 | # sagetex 98 | *.sagetex.sage 99 | *.sagetex.py 100 | *.sagetex.scmd 101 | 102 | # sympy 103 | *.sout 104 | *.sympy 105 | sympy-plots-for-*.tex/ 106 | 107 | # todonotes 108 | *.tdo 109 | 110 | # xindy 111 | *.xdy 112 | -------------------------------------------------------------------------------- /00_fp/first-prg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/00_fp/first-prg.png -------------------------------------------------------------------------------- /00_fp/fp-ce-expl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/00_fp/fp-ce-expl.png -------------------------------------------------------------------------------- /00_fp/fp-ce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/00_fp/fp-ce.png -------------------------------------------------------------------------------- /00_fp/fpc-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/00_fp/fpc-0.png -------------------------------------------------------------------------------- /00_fp/fpc-noname.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/00_fp/fpc-noname.png -------------------------------------------------------------------------------- /00_fp/output-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/00_fp/output-1.png -------------------------------------------------------------------------------- /00_fp/output-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/00_fp/output-3.png -------------------------------------------------------------------------------- /01_backtrack/01_backtrack.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \documentclass[a4paper,10pt]{problems} 5 | 6 | \begin{document} 7 | 8 | \input{01_backtrack_main.tex} 9 | 10 | \inputanswers 11 | 12 | \end{document} 13 | -------------------------------------------------------------------------------- /01_backtrack/01_backtrack_main.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \Header{Перебор с возвратом} 5 | 6 | Перебор "--- довольно своеобразный метод решения задач. На серьезных олимпиадах 7 | задачи на перебор встречаются довольно редко, но все равно во многих задачах, в 8 | которых есть <<правильное>>, эффективное решение, перебор (хорошо написанный, с 9 | крутыми отсечениями и эвристиками) может помочь набрать если не полный балл, то 10 | хотя бы половину (а то и больше). 11 | 12 | [Конечно, перебором в некотором смысле также можно называть решения, которые 13 | просто что-то перебирают, но мы перебором будем называть в первую очередь перебор 14 | некоторых, скажем так, комбинаторных объектов, написанный специфическим методом, который я и буду 15 | излагать ниже.] 16 | 17 | Основная цель перебора "--- перебрать все объекты из некоторого множества, дабы 18 | что-то сделать с каждым. Наиболее 19 | часто, вроде, встречаются три варианта: 20 | \begin{ulist} 21 | \item либо надо найти объект (любой), удовлетворяющий некоторому условию, 22 | \item либо посчитать количество таких объектов, 23 | \item либо найти в некотором смысле оптимальный объект (дающий минимальную 24 | стоимость и т.п.) 25 | \end{ulist} 26 | 27 | Конечно, перебор можно писать по-разному. Например, можно написать процедуру, которая по номеру объекта построит сам объект, а потом в основном коде просто написать цикл по номерам объектов; объекты нумеровать можно, например, средствами динамического программирования (когда буду писать про ДП, напишу и про нумерацию объектов). Можно написать код, который по 28 | объекту будет создавать в некотором смысле следующий. Но наиболее 29 | общим и в большинстве случаев не многим более сложным в реализации (а чаще "--- намного более простым и не требующим дополнительных размышлений) является 30 | рекурсивный перебор, также (насколько я понимаю) называемый перебором с 31 | возвратом, backtracking. Помимо более простой реализации, он обладает рядом других достоинств: например, в нем возможно очень легко реализовывать различные отсечения и эвристики. 32 | 33 | В тексте будут встречаться задания. К большинству из них в конце приведен ответ, а к некоторым "--- еще и подсказка. Кроме того, я думаю, что стоит написать и потестить все программы, которые я тут привожу. Только учтите, что перебор всегда работает очень долго, поэтому большие значения $n$, $k$ и других параметров подсовывать, как правило, не стоит. 34 | 35 | 36 | \input{texts/01_1_elementary.tex} 37 | \input{texts/01_2_cuts.tex} 38 | \input{texts/01_3_heur.tex} 39 | \input{texts/01_4_add.tex} 40 | 41 | -------------------------------------------------------------------------------- /01_backtrack/do.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | do_main.sh 3 | latex 01_backtrack.tex 4 | dvipdfmx -p a4 01_backtrack.dvi -------------------------------------------------------------------------------- /01_backtrack/do_main.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd texts/01_1_elementary 3 | mpost tree.mp 4 | cd ../.. 5 | -------------------------------------------------------------------------------- /01_backtrack/problems.cls: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e} 2 | \ProvidesClass{problems}[2006/11/03] 3 | 4 | % identification 5 | % initial code 6 | % declaration of options 7 | % execution of options 8 | % package loading 9 | % main code 10 | 11 | % Declaration of Options 12 | \DeclareOption{draft}{\PassOptionsToClass{draft}{article}\AtEndOfClass{\geometry{showframe}}} 13 | \DeclareOption{10pt}{\PassOptionsToClass{10pt}{article}} 14 | \DeclareOption{11pt}{\PassOptionsToClass{11pt}{article}} 15 | \DeclareOption{12pt}{\PassOptionsToClass{12pt}{article}} 16 | 17 | \hfuzz=0.1cm 18 | 19 | % Опцию a4paper будем использовать для формата, в котором задачки 20 | % печатались раньше на бумаге A4. 21 | \DeclareOption{a4paper}{ 22 | \PassOptionsToPackage{a4paper,includehead,includefoot,headheight=10pt,headsep=2mm,width=17cm,height=27cm,footskip=0.5cm}{geometry} 23 | } 24 | 25 | % Execution of Options 26 | \ProcessOptions\relax 27 | 28 | % Package Loading 29 | \LoadClass[a4paper]{article} 30 | 31 | \RequirePackage[T2A]{fontenc} 32 | \RequirePackage[utf8]{inputenc} 33 | \RequirePackage{mathtext} 34 | \RequirePackage[english,russian]{babel} 35 | \RequirePackage[dvips,final]{graphicx} 36 | \RequirePackage{wrapfig} 37 | \RequirePackage{amssymb} 38 | \RequirePackage{amsmath} 39 | \RequirePackage{amscd} 40 | \RequirePackage{array} 41 | \RequirePackage{multicol} 42 | \RequirePackage{longtable} 43 | \RequirePackage[dvips]{geometry} 44 | 45 | % Main Code 46 | \columnseprule=0.4pt 47 | \raggedbottom 48 | 49 | 50 | % AK: думаю, лучше везде использовать вариант "". 51 | %\declare@shorthand{russian}{""}{\nobreak\hskip.2em\ignorespaces} 52 | %\declare@shorthand{russian}{",}{\nobreak\hskip.2em\ignorespaces} 53 | % KAP: чтобы кавычки всегда были правильные 54 | %\declare@shorthand{russian}{"<}{<<} 55 | %\declare@shorthand{russian}{">}{>>} 56 | %---------- From package "lastpage" ------------------ 57 | \def\lastpage@putlabel{\addtocounter{page}{-1}% 58 | \immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}% 59 | \addtocounter{page}{1}} 60 | \AtEndDocument{\clearpage\lastpage@putlabel}% 61 | %---------- end of "lastpage" ------------------ 62 | 63 | \newcommand{\headernono}[1]{% 64 | \par\pagebreak[2]\vspace{1.5ex plus1ex minus .7ex}% 65 | \noindent{\large\bf\sffamily\strut #1}\par 66 | \nopagebreak\vspace{.8ex plus.8ex minus.3ex}% 67 | } 68 | 69 | \newcounter{headercount} 70 | \renewcommand{\theheadercount}{\Roman{headercount}} 71 | \newcommand{\header}[1]{% 72 | \refstepcounter{headercount}\headernono{Часть \Roman{headercount}. #1} 73 | } 74 | 75 | \newcounter{lheadercount}[headercount] 76 | \renewcommand{\thelheadercount}{\theheadercount.\arabic{lheadercount}} 77 | \newcommand{\lheadernd}[1]{% 78 | \par\pagebreak[3]\vspace{0.5ex plus1ex}% 79 | \refstepcounter{lheadercount}{\bf \S\arabic{lheadercount}. #1}\nopagebreak{}% 80 | } 81 | \newcommand{\lheader}[1]{% 82 | \lheadernd{#1}} 83 | 84 | \newcommand{\Header}[1]{% 85 | \par\pagebreak[2]\vspace{2.7ex plus 1.3ex minus 1.3ex}% 86 | \noindent{\Large\bf\sffamily #1}\par 87 | \nopagebreak\vspace{2ex plus 1ex minus 1ex}% 88 | } 89 | 90 | \newcounter{llheadercount}[lheadercount] 91 | \renewcommand{\thellheadercount}{\thelheadercount.\arabic{llheadercount}} 92 | \newcommand{\llheader}{% 93 | \par\pagebreak[3]% 94 | \refstepcounter{llheadercount}{\bf \arabic{llheadercount}.} % 95 | } 96 | 97 | %\def\nought{\ensuremath{{\mkern-3.25mu{\not}\mkern3.25mu\mbox{\tt0}}}} 98 | \def\slnought{{\tt\O}} 99 | 100 | \newcommand{\todo}[1]{\marginpar{\raggedright\footnotesize!~TODO:\\#1}} 101 | 102 | \renewcommand{\@oddhead}{} 103 | 104 | \renewcommand{\@oddfoot}{% 105 | \vbox{% 106 | \hrule\vspace{0.1cm}% 107 | \hbox to \textwidth{% 108 | \sf\footnotesize% 109 | \hfill\strut Страница \thepage\ из \pageref{LastPage}\hfill% 110 | }}} 111 | 112 | \renewcommand{\leq}{\leqslant} 113 | \renewcommand{\le}{\leqslant} 114 | \renewcommand{\geq}{\geqslant} 115 | 116 | \newcommand{\unit}[1]{\mbox{ \rm #1}} 117 | % \vstring#1 118 | % Написать #1 как строку вх/вых файла (в кавычках шрифтом \tt без 119 | % переносов) 120 | \newcommand*{\vstring}[1]{`\mbox{\tt#1}'} 121 | 122 | %БАГ: пока не работает генерация автоматических ссылок на пункты перечня 123 | \newcounter{tmp} 124 | 125 | \newenvironment{ulists}[2]{% 126 | \bgroup\begin{list}{#1}{\topsep=0.6ex plus 0.3ex minus 0.6ex \partopsep=0.6ex minus 0.6ex \parsep=0pt \itemsep=0pt #2}% 127 | } 128 | {\end{list}\egroup} 129 | 130 | \newenvironment{ulist}{% 131 | \begin{ulists}{$\bullet$}{}% 132 | } 133 | {\end{ulists}} 134 | 135 | \newenvironment{olist}{% 136 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 137 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{}% 138 | } 139 | {\end{ulists}} 140 | 141 | \newenvironment{olistzero}{% 142 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 143 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \partopsep=0ex}% 144 | } 145 | {\end{ulists}} 146 | 147 | \newenvironment{wideolist}{% 148 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 149 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \parsep=0pt \itemsep=0pt \leftmargin=0pt \itemindent=\labelwidth}% 150 | } 151 | {\end{ulists}} 152 | 153 | % Нумерованный список с сквозной нумерацией 154 | \newcounter{olistcount}\renewcommand{\theolistcount}{\arabic{olistcount}} 155 | \newcommand{\resetolist}{\setcounter{olistcount}{0}} 156 | \newenvironment{olistc}{% 157 | \renewcommand{\theolistcount}{\arabic{olistcount}} 158 | \begin{ulists}{\refstepcounter{olistcount}\theolistcount.}{}% 159 | } 160 | {\end{ulists}} 161 | 162 | % Нумерованный список для использования в тексте, когда каждый пункт 163 | % пишется с маленькой буквы и отделяется ";". 164 | % Здесь помечается арабской цифрой со скобкой. 165 | \newenvironment{tllist}{% 166 | \setcounter{tmp}{0} 167 | \begin{ulists}{\refstepcounter{tmp}\thetmp)}{}% 168 | } 169 | {\end{ulists}} 170 | 171 | \newcommand*{\hm}[1]{#1\nobreak\discretionary{}{\hbox{$\mathsurround=0pt #1$}}{}} 172 | 173 | \newcommand{\wvec}[1]{\overrightarrow{#1}} 174 | 175 | \newcommand{\wnote}[1]{{\sl [~#1~]\todo{!}}} 176 | 177 | \relpenalty=10000 178 | \binoppenalty=10000 179 | 180 | \newcommand{\OR}{\mathrel{\mathrm{or}}} 181 | \newcommand{\XOR}{\mathrel{\mathrm{xor}}} 182 | \newcommand{\AND}{\mathrel{\mathrm{and}}} 183 | \newcommand{\NOT}{\mathop{\mathrm{not}}} 184 | \newcommand{\SHL}{\mathop{\mathrm{shl}}} 185 | \newcommand{\SHR}{\mathop{\mathrm{shr}}} 186 | 187 | 188 | % Суммарная ширина столбцов в двухколоночной таблице, выровненной по ширине 189 | \newlength\twowidth 190 | \newcommand{\settwowidth}{ 191 | \twowidth=\textwidth 192 | \addtolength\twowidth{-4\tabcolsep} 193 | \addtolength\twowidth{-3\arrayrulewidth} 194 | } 195 | \AtBeginDocument{\settwowidth}%т.к. \textwidth надо сначала установить 196 | 197 | % --= поддержка примеров программ, сделаных conv.pas =-- 198 | % Это для борьбы с разрывами страницы после окружений multicols 199 | \newlength{\cs@topskip} 200 | \newlength{\cs@bottom} 201 | \newlength{\cs@bottomback} 202 | \newlength{\cs@top} 203 | \cs@topskip=1.5ex 204 | \cs@bottom=1.5ex 205 | \cs@bottomback=1ex plus 0.5ex minus 0.3ex 206 | \footnotesize\cs@top=2.4ex\normalsize 207 | 208 | \newenvironment{codesamplec}[1] 209 | {% локальные определения: 210 | \newcommand{\codelf}{\kern-1.5em\\}% 211 | \newcommand{\codespace}{{\ttfamily\symbol{`\ }}}% 212 | \newcommand{\codetok}[1]{{\bfseries##1}}% 213 | \newcommand{\codecmt}[1]{{\ttfamily\slshape##1}}% 214 | \vspace{0.5ex plus 0.3ex minus 0.1ex} 215 | \topskip=\cs@topskip%KAP: не знаю почему, но работает :):):) !!! От этого параметра зависимость --- пороговая. Пришлось еще подрегулировать \vspace строкой ниже 216 | %KAP: тут где-то еще видимо затесался vspace с plus/minus компонентой, так что, если сильно ужимать страницу, то все переедет... 217 | \par\begin{multicols}{#1}[\footnotesize\hrule\nopagebreak\vspace{-\cs@top}]\tt\noindent} 218 | {\end{multicols}\par\vspace*{-\cs@bottom}\hrule\vspace*{\cs@bottomback}\pagebreak[0]} 219 | 220 | \newenvironment{codesample}{\begin{codesamplec}{2}}{\end{codesamplec}} 221 | 222 | \newenvironment{codesampleo} 223 | {\vspace{0.5ex plus 0.3ex minus 0.1ex} 224 | \par\footnotesize\hrule\nopagebreak\vspace{-1.3ex}\tt\noindent} 225 | {\par\nopagebreak\vspace{-1.3ex}\hrule\vspace{\cs@bottomback}} 226 | 227 | % --= * =-- 228 | 229 | \newcommand{\noten}[2]{{\vspace{0.1cm}\par\pagebreak[3]\small \textit{#1:} #2 \vspace{0.1cm plus 0.1cm}\par}} 230 | \newcommand{\note}[1]{\noten{Примечание}{#1}} 231 | 232 | \newcommand{\eps}{\varepsilon} 233 | 234 | \newcommand{\epigraph}[2]{%\hangindent=0.4\textwidth\begin{flushright}\small\textit{#1}\par\footnotesize#2\par\end{flushright} 235 | {\parindent=0cm 236 | \parshape 1 0.4\textwidth 0.6\textwidth 237 | \begin{flushright}% 238 | \small\textit{#1}\par% 239 | \vspace{0.1cm}% 240 | \footnotesize#2\par% 241 | \end{flushright}}% 242 | } 243 | 244 | \newcounter{taskcount} 245 | \renewcommand{\thetaskcount}{\arabic{taskcount}} 246 | \newcommand{\taskon}[2]{% 247 | \refstepcounter{taskcount}% 248 | \textbf{#1\mbox{~}\thetaskcount:} {\it #2}% 249 | } 250 | \newcommand{\tasko}[1]{\taskon{Задание}{#1}} 251 | 252 | \newcommand{\hint}[2]{\textbf{Посказка \ref{#1}:} #2} 253 | 254 | \newcommand{\answer}[2]{\textbf{Ответ \ref{#1}:} #2} 255 | 256 | \renewcommand{\ddots}{\,\,.\,.\,\,} 257 | 258 | %ANSWERS + 259 | \newlinechar=`\^^M 260 | 261 | \newwrite\tsk 262 | \immediate\openout\tsk=\jobname.tsk\relax 263 | \newwrite\ans 264 | \immediate\openout\ans=\jobname.ans\relax 265 | \newwrite\hnt 266 | \immediate\openout\hnt=\jobname.hnt\relax 267 | \newwrite\dup 268 | 269 | \def\makerusother{% 270 | \@tempcnta128\relax% 271 | \loop% 272 | \catcode\@tempcnta12% 273 | \ifnum\@tempcnta<255\relax% 274 | \advance\@tempcnta\@ne% 275 | \repeat% 276 | } 277 | 278 | \def\makeallother{% 279 | \let\do\@makeother\dospecials% 280 | \makerusother% 281 | } 282 | 283 | \def\writeansno#1#2{% 284 | \begingroup% 285 | \makeallother% 286 | \obeylines% 287 | \long\def\copyans#2##1#2{% 288 | \def\tmp{##1}% 289 | \if\tmp\empty% 290 | \else% 291 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 292 | \immediate\write#1{##1}% 293 | \fi% 294 | \endgroup\afterwriteans% 295 | }% 296 | \copyans#2% 297 | } 298 | 299 | \def\dupeans#1#2{% 300 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 301 | \immediate\openout\dup=\jobname.dup\relax% 302 | \begingroup% 303 | \makeallother% 304 | \obeylines% 305 | \long\def\copyans#2##1#2{% 306 | \immediate\write#1{##1}% 307 | \immediate\write\dup{##1\noexpand\endinput}% 308 | \endgroup\immediate\closeout\dup% 309 | \input{\jobname.dup}% 310 | \afterwriteans% 311 | }% 312 | \copyans#2% 313 | } 314 | 315 | \def\tasknn#1{% 316 | \endgroup% 317 | \refstepcounter{taskcount}% 318 | \gdef\taskname{#1}% 319 | \immediate\openout\dup=\jobname.dup\relax% 320 | \immediate\write\dup{\noexpand\taskcaption{\taskname{}\noexpand~\thetaskcount:}\noexpand\endinput}% 321 | \immediate\closeout\dup% 322 | \input{\jobname.dup}% 323 | \let\afterwriteans\relax% 324 | \gdef\afterwriteans{% 325 | \gdef\afterwriteans{% 326 | \let\afterwriteans\endgroup% 327 | \writeansno\ans% 328 | }% 329 | \writeansno\hnt% 330 | } 331 | \begingroup\it% 332 | \dupeans\tsk% 333 | } 334 | 335 | \def\taskn{% 336 | \begingroup\makerusother\tasknn% 337 | } 338 | 339 | {\makerusother 340 | \gdef\deftaskname{Задание} 341 | } 342 | 343 | \def\task{\taskn{\deftaskname}} 344 | 345 | \def\taskcaption#1{\textbf{#1}} 346 | 347 | \long\def\answer#1#2{ 348 | \par\pagebreak[3]\mbox{\taskcaption{#1} (стр. #2):} 349 | } 350 | 351 | \def\inputanswers{% 352 | \immediate\closeout\tsk 353 | \immediate\closeout\hnt 354 | \immediate\closeout\ans 355 | \eject\header{Условия всех задач} 356 | \input{\jobname.tsk} 357 | \eject\header{Подсказки} 358 | \input{\jobname.hnt} 359 | \eject\header{Ответы} 360 | \input{\jobname.ans} 361 | } 362 | 363 | -------------------------------------------------------------------------------- /01_backtrack/texts/01_1_elementary/tree.mp: -------------------------------------------------------------------------------- 1 | prologues:=3; 2 | 3 | dx:=0.4cm; 4 | dy:=1cm; 5 | levmax:=3; 6 | input TEX.mp 7 | pw:=0.2cm; 8 | 9 | pair labelshift; 10 | labelshift:=(0.3dx,0); 11 | 12 | def drawtree(expr i,j,x,y,lev)= 13 | numeric xx,yy; 14 | 15 | if lev>. 19 | Если же вам требовалось (редкий случай) вывести \textit{все} решения, то ничего не 20 | остаётся, как их все найденные на данный момент и вывести, и завершить работу (про вывод 21 | \textit{всех} решений см. ниже). 22 | \item В задачах на подсчёт числа объектов ничего не остаётся, как вывести, сколько 23 | вы уже насчитали. Конечно, скорее всего это будет неправильно (ваша программа 24 | работала секунду, насчитала, допустим 1432 объекта, и хочет работать ещё 25 | секунду\dots{} неужто она не найдёт ни одного объекта больше? :) а если найдёт, 26 | то, значит, $1432$ "--- неверный ответ), но работать больше нельзя и ничего 27 | лучше тут, видимо, не придумаешь. 28 | \end{ulist} 29 | 30 | 31 | \note{Тестирование программы с отсечением по времени на компьютере жюри выглядит весьма эффектно, 32 | особенно если вы смотрите непосредственно в экран тестирующего компьютера, на 33 | котором пишется, сколько времени осталось: время приближается к TL, и все уже 34 | готовы увидеть TL, но нет "--- за доли секунды до TL ваша программа завершается, запускается чекер и вы видите WA "--- что ж, не повезло "--- или OK "--- ура, повезло.} 35 | 36 | Как технически делать отсечение по времени? В Borland Pascal (как и в 37 | любых DOS-программах) есть очень удобная вещь: по адресу 0:\$46С (т.е. в ячейке памяти с абсолютным номером $46\mathrm C_{16}$) лежат четыре 38 | байта, которые образуют переменную типа $longint$. Её значение автоматически (!) 39 | увеличивается на единицу примерно 18 раз в секунду (за счёт прерывания 40 | таймера). Поэтому отсечение по времени можно писать так: 41 | \begin{codesampleo}\begin{verbatim} 42 | var t:longint absolute 0:$46c; 43 | {такая конструкция с absolute позволяет указать абсолютный адрес, 44 | где в памяти будет храниться значение переменной} 45 | t0:longint; 46 | 47 | procedure find(...) 48 | begin 49 | if i>k... 50 | end; 51 | if t>t0+18 then begin {считая, что ограничение времени 1 секунда} 52 | out; {процедура out выводит текущее найденное решение в выходной файл} 53 | halt; 54 | end; 55 | ... 56 | end; 57 | 58 | begin {основная программа} 59 | t0:=t; {сохраним начальный момент времени в t0} 60 | ... 61 | end. 62 | \end{verbatim} 63 | \end{codesampleo} 64 | может, стоит ставить 17, а не 18, на всякий случай, и т.п. 65 | 66 | В Windows"=программах все не так просто, в частности потому, что нужно учитывать 67 | процессорное время, потраченное вашей программой. Насколько я понимаю, есть 68 | функция $getTickCount$, но считается, что она подтормаживает и \textit{каждый} раз 69 | в функции $find$ её вызывать "--- это очень медленно. Тогда может иметь смысл 70 | завести ещё глобальную переменную $nn$, которая будет считать, сколько раз вы 71 | вошли в $find$, и только, например, каждый $1024$-ый раз проверять. Типа того: 72 | 73 | \begin{codesample}\begin{verbatim} 74 | var t:longint; 75 | nn:longint; 76 | 77 | procedure find... 78 | begin 79 | if i>k... 80 | end; 81 | if (n and 1023=0)and(gettickcount>t0+1000) then begin 82 | ... 83 | end; 84 | inc(nn); 85 | ... 86 | 87 | ... 88 | 89 | begin 90 | t0:=gettickcount; 91 | nn:=0; 92 | ... 93 | end. 94 | 95 | 96 | 97 | \end{verbatim} 98 | \end{codesample} 99 | 100 | (\texttt{n0 and 1023}, а не \texttt{n0 mod 1024}, поскольку первое работает намного быстрее; по той же причине проверяю каждые 1024, а не каждые 1000 раз). На само деле, конечно, необходимая частота проверок сильно зависит от задачи: иногда может понадобиться и каждый $65\,536$-ой раз проверять и т.п.; каждый раз стоит подбирать константу заново, чтобы проверки были достаточно частыми, но не слишком частыми. 101 | 102 | И ещё, конечно, можно это организовать и по"=другому: 103 | \begin{codesampleo}\begin{verbatim} 104 | if (n=1000) then begin 105 | n:=0; 106 | if (gettickcount>t0+1000) then begin 107 | ... 108 | end; 109 | end; 110 | inc(nn); 111 | \end{verbatim} 112 | \end{codesampleo} 113 | т.е. при проверке сбрасывать счётчик в ноль. Теперь взятие остатка по модулю не нужно вообще, и можно работать с любым модулем. Но подобная проверка все равно не сильно быстрее проверки по модулю <<два в степени $k$>>, поэтому как вам больше нравится, так и пишите. Первый способ позволяет вам также узнать в конце программы, сколько же раз на самом деле вызывалась ваша функция. 114 | 115 | \lheader{Перебор двумерного массива} Иногда объекты, которые мы перебираем, проще представлять в виде двумерного 116 | массива (а не одномерного, как было всегда раньше). Пусть, например, надо 117 | перебрать все способы заполнения \textit{матрицы} $N\times N$ нулями и единицами. Можно это 118 | написать так: 119 | 120 | \begin{codesampleo}\begin{verbatim} 121 | procedure find(i,j:integer); {i,j --- координаты клетки, которую перебираем} 122 | begin 123 | if i>n then begin {если кончилась вся матрица} 124 | check; 125 | exit; 126 | end; 127 | if j>n then begin {если кончилась текущая строка} 128 | find(i+1,1); {то перейти к следующей} 129 | exit; 130 | end; 131 | a[i,j]:=0; 132 | find(i,j+1); 133 | a[i,j]:=1; 134 | find(i,j+1); 135 | end; 136 | \end{verbatim} 137 | \end{codesampleo} 138 | 139 | Осознайте этот пример. 140 | 141 | \lheader{Вариации порядка выбора элементов} 142 | (Это не то, что обсуждалось в разделе про эвристики.) Иногда имеет смысл 143 | заполнять элементы ответа не в том порядке, в котором приходит в голову, а продумать, 144 | в каком. Например, пусть наша задача "--- дано $N^2$ чисел, проверить, можно ли из 145 | них составить магический квадрат (т.е. квадрат, в котором сумма каждой строки 146 | равна сумме каждого столбца). Можно, конечно, перебирать так, как написано в 147 | предыдущем пункте: т.е. выбирать значения для первой строки, потом для второй и 148 | т.д\dots Но можно поступить так: в $find(1)$ перебираем значение клетки $(1,1)$, в 149 | $find(2)$ "--- $(1,2)$, \dots $find(n)$ "--- $(1,n)$, $find(n+1)$ "--- $(2,1)$ и внимание! 150 | $find(n+2)$ "--- $(3,1)$, $find(n+3)$ "--- $(4,1)$ и т.д., потом остаток второй строки, 151 | потом остаток второго столбца и т.д., в таблице справа следующего абзаца для $N=5$ приведены номера, какая клетка какой по счету будет. 152 | 153 | \begin{wrapfigure}[6]{r}{4cm}\vspace*{-0.3cm} 154 | \begin{tabular}{|c|c|c|c|c|}\hline 155 | 1&2&3&4&5\\\hline 156 | 6&10&11&12&13\\\hline 157 | 7&14&17&18&19\\\hline 158 | 8&15&20&22&23\\\hline 159 | 9&16&21&24&25\\\hline 160 | \end{tabular} 161 | \end{wrapfigure} 162 | Смысл в том, что в этой задаче есть естественное отсечение: если мы заполнили 163 | очередную строку или столбец, то стоит сразу проверить, что его сумма равна 164 | сумме всех чисел, делённой на $N$ (очевидно, что именно такая должна быть сумма 165 | каждой строки и каждого столбца). Поэтому стоит заполнять таблицу в таком 166 | порядке, чтобы проверять можно быть как можно быстрее. Если заполнять построчно, 167 | то проверять можно будет после первой строки (при глубине рекурсии $N$), после 168 | второй ($2N$), после третьей ($3N$), и т.д., зато в конце "--- на всей последней 169 | строке будем проверять суммы столбцов. 170 | 171 | А если делать заполнять по очереди строки и столбцы (как описано два абзаца 172 | назад и показано в примере справа), то отсечения будут: после первой строки (на глубине $N$), после первого столбца (на глубине $2N-1$, а не $2N$ (!)), после второй строки ($3N-2$, а не $3N$) и т.д. "--- т.е. отсечения будут раньше и программа будет работать быстрее. 173 | 174 | Аналогичные идеи могут быть и в других задачах, хотя, наверное, весьма редко. 175 | 176 | \lheader{Вывод всех оптимальных решений} 177 | Пусть надо вывести \textit{все} оптимальные решения. Можно, конечно, завести большой 178 | массив, куда их записывать, но имхо проще поступить так: при нахождении 179 | очередного оптимального решения просто выводить его сразу в файл. Находится ещё одно столь же хорошее решение "--- его тоже выводим туда же. Если же 180 | находится решение, которое ещё оптимальнее, чем все, что было раньше, то делаем 181 | $rewrite$ "--- и все решения, которые были выведены раньше, сотрутся. Это все 182 | делается в процедуре $check$, конечно. 183 | 184 | Пример: пусть в задаче про удаление чисел надо было бы вывести \textit{все} оптимальные решения. Тогда пишем 185 | \begin{codesampleo}\begin{verbatim} 186 | procedure check; 187 | var i:integer; 188 | begin 189 | if cur$). 212 | 213 | Кстати, ещё мысль. Аналогично можно поступить и если выводить надо 214 | только одно решение. Можно его не сохранять в $ans$, а сразу выводить 215 | 216 | \begin{codesampleo}\begin{verbatim} 217 | procedure check; 218 | var i:integer; 219 | begin 220 | if cur}{>>} 56 | %---------- From package "lastpage" ------------------ 57 | \def\lastpage@putlabel{\addtocounter{page}{-1}% 58 | \immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}% 59 | \addtocounter{page}{1}} 60 | \AtEndDocument{\clearpage\lastpage@putlabel}% 61 | %---------- end of "lastpage" ------------------ 62 | 63 | \newcommand{\headernono}[1]{% 64 | \par\pagebreak[2]\vspace{1.5ex plus1ex minus .7ex}% 65 | \noindent{\large\bf\sffamily\strut #1}\par 66 | \nopagebreak\vspace{.8ex plus.8ex minus.3ex}% 67 | } 68 | 69 | \newcounter{headercount} 70 | \renewcommand{\theheadercount}{\Roman{headercount}} 71 | \newcommand{\header}[1]{% 72 | \refstepcounter{headercount}\headernono{Часть \Roman{headercount}. #1} 73 | } 74 | 75 | \newcounter{lheadercount}[headercount] 76 | \renewcommand{\thelheadercount}{\theheadercount.\arabic{lheadercount}} 77 | \newcommand{\lheader}[1]{% 78 | \par\pagebreak[3]\vspace{0.5ex plus1ex}% 79 | \refstepcounter{lheadercount}{\bf \S\arabic{lheadercount}. #1.}\nopagebreak{}% 80 | } 81 | 82 | \newcommand{\Header}[1]{% 83 | \par\pagebreak[2]\vspace{2.7ex plus 1.3ex minus 1.3ex}% 84 | \noindent{\Large\bf\sffamily #1}\par 85 | \nopagebreak\vspace{2ex plus 1ex minus 1ex}% 86 | } 87 | 88 | \newcounter{llheadercount}[lheadercount] 89 | \renewcommand{\thellheadercount}{\thelheadercount.\arabic{llheadercount}} 90 | \newcommand{\llheader}{% 91 | \par\pagebreak[3]% 92 | \refstepcounter{llheadercount}{\bf \arabic{llheadercount}.} % 93 | } 94 | 95 | %\def\nought{\ensuremath{{\mkern-3.25mu{\not}\mkern3.25mu\mbox{\tt0}}}} 96 | \def\slnought{{\tt\O}} 97 | 98 | \newcommand{\todo}[1]{\marginpar{\raggedright\footnotesize!~TODO:\\#1}} 99 | 100 | \renewcommand{\@oddhead}{} 101 | 102 | \renewcommand{\@oddfoot}{% 103 | \vbox{% 104 | \hrule\vspace{0.1cm}% 105 | \hbox to \textwidth{% 106 | \sf\footnotesize% 107 | \hfill\strut Страница \thepage\ из \pageref{LastPage}\hfill% 108 | }}} 109 | 110 | \renewcommand{\leq}{\leqslant} 111 | \renewcommand{\le}{\leqslant} 112 | \renewcommand{\geq}{\geqslant} 113 | 114 | \newcommand{\unit}[1]{\mbox{ \rm #1}} 115 | % \vstring#1 116 | % Написать #1 как строку вх/вых файла (в кавычках шрифтом \tt без 117 | % переносов) 118 | \newcommand*{\vstring}[1]{`\mbox{\tt#1}'} 119 | 120 | %БАГ: пока не работает генерация автоматических ссылок на пункты перечня 121 | \newcounter{tmp} 122 | 123 | \newenvironment{ulists}[2]{% 124 | \bgroup\begin{list}{#1}{\topsep=0.6ex plus 0.3ex minus 0.6ex \partopsep=0.6ex minus 0.6ex \parsep=0pt \itemsep=0pt #2}% 125 | } 126 | {\end{list}\egroup} 127 | 128 | \newenvironment{ulist}{% 129 | \begin{ulists}{$\bullet$}{}% 130 | } 131 | {\end{ulists}} 132 | 133 | \newenvironment{olist}{% 134 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 135 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{}% 136 | } 137 | {\end{ulists}} 138 | 139 | \newenvironment{olistzero}{% 140 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 141 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \partopsep=0ex}% 142 | } 143 | {\end{ulists}} 144 | 145 | \newenvironment{wideolist}{% 146 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 147 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \parsep=0pt \itemsep=0pt \leftmargin=0pt \itemindent=\labelwidth}% 148 | } 149 | {\end{ulists}} 150 | 151 | % Нумерованный список с сквозной нумерацией 152 | \newcounter{olistcount}\renewcommand{\theolistcount}{\arabic{olistcount}} 153 | \newcommand{\resetolist}{\setcounter{olistcount}{0}} 154 | \newenvironment{olistc}{% 155 | \renewcommand{\theolistcount}{\arabic{olistcount}} 156 | \begin{ulists}{\refstepcounter{olistcount}\theolistcount.}{}% 157 | } 158 | {\end{ulists}} 159 | 160 | % Нумерованный список для использования в тексте, когда каждый пункт 161 | % пишется с маленькой буквы и отделяется ";". 162 | % Здесь помечается арабской цифрой со скобкой. 163 | \newenvironment{tllist}{% 164 | \setcounter{tmp}{0} 165 | \begin{ulists}{\refstepcounter{tmp}\thetmp)}{}% 166 | } 167 | {\end{ulists}} 168 | 169 | \newcommand*{\hm}[1]{#1\nobreak\discretionary{}{\hbox{$\mathsurround=0pt #1$}}{}} 170 | 171 | \newcommand{\wvec}[1]{\overrightarrow{#1}} 172 | 173 | \newcommand{\wnote}[1]{{\sl [~#1~]\todo{!}}} 174 | 175 | \relpenalty=10000 176 | \binoppenalty=10000 177 | 178 | \newcommand{\OR}{\mathrel{\mathrm{or}}} 179 | \newcommand{\XOR}{\mathrel{\mathrm{xor}}} 180 | \newcommand{\AND}{\mathrel{\mathrm{and}}} 181 | \newcommand{\NOT}{\mathop{\mathrm{not}}} 182 | \newcommand{\SHL}{\mathop{\mathrm{shl}}} 183 | \newcommand{\SHR}{\mathop{\mathrm{shr}}} 184 | 185 | 186 | % Суммарная ширина столбцов в двухколоночной таблице, выровненной по ширине 187 | \newlength\twowidth 188 | \newcommand{\settwowidth}{ 189 | \twowidth=\textwidth 190 | \addtolength\twowidth{-4\tabcolsep} 191 | \addtolength\twowidth{-3\arrayrulewidth} 192 | } 193 | \AtBeginDocument{\settwowidth}%т.к. \textwidth надо сначала установить 194 | 195 | % --= поддержка примеров программ, сделаных conv.pas =-- 196 | % Это для борьбы с разрывами страницы после окружений multicols 197 | \newlength{\cs@topskip} 198 | \newlength{\cs@bottom} 199 | \newlength{\cs@bottomback} 200 | \newlength{\cs@top} 201 | \cs@topskip=1.5ex 202 | \cs@bottom=1.5ex 203 | \cs@bottomback=1ex plus 0.5ex minus 0.3ex 204 | \footnotesize\cs@top=2.4ex\normalsize 205 | 206 | \newenvironment{codesamplec}[1] 207 | {% локальные определения: 208 | \newcommand{\codelf}{\kern-1.5em\\}% 209 | \newcommand{\codespace}{{\ttfamily\symbol{`\ }}}% 210 | \newcommand{\codetok}[1]{{\bfseries##1}}% 211 | \newcommand{\codecmt}[1]{{\ttfamily\slshape##1}}% 212 | \vspace{0.5ex plus 0.3ex minus 0.1ex} 213 | \topskip=\cs@topskip%KAP: не знаю почему, но работает :):):) !!! От этого параметра зависимость --- пороговая. Пришлось еще подрегулировать \vspace строкой ниже 214 | %KAP: тут где-то еще видимо затесался vspace с plus/minus компонентой, так что, если сильно ужимать страницу, то все переедет... 215 | \par\begin{multicols}{#1}[\footnotesize\hrule\nopagebreak\vspace{-\cs@top}]\tt\noindent} 216 | {\end{multicols}\par\vspace*{-\cs@bottom}\hrule\vspace*{\cs@bottomback}\pagebreak[0]} 217 | 218 | \newenvironment{codesample}{\begin{codesamplec}{2}}{\end{codesamplec}} 219 | 220 | \newenvironment{codesampleo} 221 | {\vspace{0.5ex plus 0.3ex minus 0.1ex} 222 | \par\footnotesize\hrule\nopagebreak\vspace{-1.3ex}\tt\noindent} 223 | {\par\nopagebreak\vspace{-1.3ex}\hrule\vspace{\cs@bottomback}} 224 | 225 | % --= * =-- 226 | 227 | \newcommand{\noten}[2]{{\vspace{0.1cm}\par\pagebreak[3]\small \textit{#1:} #2 \vspace{0.1cm plus 0.1cm}\par}} 228 | \newcommand{\note}[1]{\noten{Примечание}{#1}} 229 | 230 | \newcommand{\eps}{\varepsilon} 231 | 232 | \newcommand{\epigraph}[2]{%\hangindent=0.4\textwidth\begin{flushright}\small\textit{#1}\par\footnotesize#2\par\end{flushright} 233 | {\parindent=0cm 234 | \parshape 1 0.4\textwidth 0.6\textwidth 235 | \begin{flushright}% 236 | \small\textit{#1}\par% 237 | \vspace{0.1cm}% 238 | \footnotesize#2\par% 239 | \end{flushright}}% 240 | } 241 | 242 | \newcounter{taskcount} 243 | \renewcommand{\thetaskcount}{\arabic{taskcount}} 244 | \newcommand{\taskon}[2]{% 245 | \refstepcounter{taskcount}% 246 | \textbf{#1\mbox{~}\thetaskcount:} {\it #2}% 247 | } 248 | \newcommand{\tasko}[1]{\taskon{Задание}{#1}} 249 | 250 | \newcommand{\hint}[2]{\textbf{Посказка \ref{#1}:} #2} 251 | 252 | \newcommand{\answer}[2]{\textbf{Ответ \ref{#1}:} #2} 253 | 254 | \renewcommand{\ddots}{\,\,.\,.\,\,} 255 | 256 | %ANSWERS + 257 | \newlinechar=`\^^M 258 | 259 | \newwrite\tsk 260 | \immediate\openout\tsk=\jobname.tsk\relax 261 | \newwrite\ans 262 | \immediate\openout\ans=\jobname.ans\relax 263 | \newwrite\hnt 264 | \immediate\openout\hnt=\jobname.hnt\relax 265 | \newwrite\dup 266 | 267 | \def\makerusother{% 268 | \@tempcnta128\relax% 269 | \loop% 270 | \catcode\@tempcnta12% 271 | \ifnum\@tempcnta<255\relax% 272 | \advance\@tempcnta\@ne% 273 | \repeat% 274 | } 275 | 276 | \def\makeallother{% 277 | \let\do\@makeother\dospecials% 278 | \makerusother% 279 | } 280 | 281 | \def\writeansno#1#2{% 282 | \begingroup% 283 | \makeallother% 284 | \obeylines% 285 | \long\def\copyans#2##1#2{% 286 | \def\tmp{##1}% 287 | \if\tmp\empty% 288 | \else% 289 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 290 | \immediate\write#1{##1}% 291 | \fi% 292 | \endgroup\afterwriteans% 293 | }% 294 | \copyans#2% 295 | } 296 | 297 | \def\dupeans#1#2{% 298 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 299 | \immediate\openout\dup=\jobname.dup\relax% 300 | \begingroup% 301 | \makeallother% 302 | \obeylines% 303 | \long\def\copyans#2##1#2{% 304 | \immediate\write#1{##1}% 305 | \immediate\write\dup{##1\noexpand\endinput}% 306 | \endgroup\immediate\closeout\dup% 307 | \input{\jobname.dup}% 308 | \afterwriteans% 309 | }% 310 | \copyans#2% 311 | } 312 | 313 | \def\tasknn#1{% 314 | \endgroup% 315 | \refstepcounter{taskcount}% 316 | \gdef\taskname{#1}% 317 | \immediate\openout\dup=\jobname.dup\relax% 318 | \immediate\write\dup{\noexpand\taskcaption{\taskname{}\noexpand~\thetaskcount:}\noexpand\endinput}% 319 | \immediate\closeout\dup% 320 | \input{\jobname.dup}% 321 | \let\afterwriteans\relax% 322 | \gdef\afterwriteans{% 323 | \gdef\afterwriteans{% 324 | \let\afterwriteans\endgroup% 325 | \writeansno\ans% 326 | }% 327 | \writeansno\hnt% 328 | } 329 | \begingroup\it% 330 | \dupeans\tsk% 331 | } 332 | 333 | \def\taskn{% 334 | \begingroup\makerusother\tasknn% 335 | } 336 | 337 | {\makerusother 338 | \gdef\deftaskname{Задание} 339 | } 340 | 341 | \def\task{\taskn{\deftaskname}} 342 | 343 | \def\taskcaption#1{\textbf{#1}} 344 | 345 | \long\def\answer#1#2{ 346 | \par\pagebreak[3]\mbox{\taskcaption{#1} (стр. #2):} 347 | } 348 | 349 | \def\inputanswers{% 350 | \immediate\closeout\tsk 351 | \immediate\closeout\hnt 352 | \immediate\closeout\ans 353 | \eject\header{Условия всех задач} 354 | \input{\jobname.tsk} 355 | \eject\header{Подсказки} 356 | \input{\jobname.hnt} 357 | \eject\header{Ответы} 358 | \input{\jobname.ans} 359 | } 360 | 361 | -------------------------------------------------------------------------------- /03_shortideas/03_shortideas.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \documentclass[a4paper,10pt]{problems} 5 | 6 | \iffalse 7 | \newcommand{\OR}{\mathrel{\mathrm{or}}} 8 | \newcommand{\XOR}{\mathrel{\mathrm{xor}}} 9 | \newcommand{\AND}{\mathrel{\mathrm{and}}} 10 | \newcommand{\NOT}{\mathop{\mathrm{not}}} 11 | \newcommand{\SHL}{\mathop{\mathrm{shl}}} 12 | \newcommand{\SHR}{\mathop{\mathrm{shr}}} 13 | \fi 14 | 15 | \begin{document} 16 | 17 | \input{03_shortideas_main.tex} 18 | 19 | \inputanswers 20 | 21 | \end{document} 22 | -------------------------------------------------------------------------------- /03_shortideas/03_shortideas_main.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \Header{%Тема III. 5 | Различные около\-программисткие идеи и замечания} 6 | 7 | {\raggedleft\it 8 | Некоторые разделы этой части написаны Оксаной Побуринной. 9 | \par} 10 | 11 | %Решил третью тему составить из нескольких более"=менее коротких кусков, 12 | %часть из которых, как мне кажется, стоит понимать до дальнейшего материала :), 13 | %а часть просто может быть полезна или просто интересна. 14 | 15 | \header{Непрограммистские замечания} 16 | \input{ideas/03_1_encodings.tex} 17 | \input{ideas/03_2_Axor32.tex} 18 | 19 | \header{Замечания о языке программирования} 20 | Буду о паскале: Free Pascal и Delphi. Про Borland Pascal говорить ничего не буду, это уже совсем 21 | устаревшая IDE. 22 | 23 | Не забывайте про комбинацию клафиш Ctrl-F1, т.е. не забывайте, что многое можно (либо 24 | правду, либо полуправду, но все равно идеи поймете) посмотреть в справке. Там, может быть, все 25 | будет не очень хорошо объяснено, но вы поймете и додумаете сами. 26 | 27 | \input{ideas/03_3_types.tex} 28 | \input{ideas/03_4_compswitches.tex} 29 | \input{ideas/03_5_bitandor.tex} 30 | \input{ideas/03_6_fileof.tex} 31 | \input{ideas/03_7_optimes.tex} 32 | 33 | \header{Программистские идеи} 34 | \input{ideas/03_8_changetest.tex} 35 | \input{ideas/03_9_quickpow.tex} 36 | \input{ideas/03_10_GCDnodiv.tex} 37 | \input{ideas/03_11_quicksearch.tex} 38 | \input{ideas/03_12_noinitarray.tex} 39 | \input{ideas/03_13_period.tex} 40 | \input{ideas/03_14_names.tex} 41 | -------------------------------------------------------------------------------- /03_shortideas/do.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | latex 03_shortideas.tex 3 | dvips -t a4 03_shortideas.dvi 4 | ps2pdf 03_shortideas.ps -------------------------------------------------------------------------------- /03_shortideas/encodings.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/encodings.pas -------------------------------------------------------------------------------- /03_shortideas/graphics.cfg: -------------------------------------------------------------------------------- 1 | \ProvidesFile{graphics.cfg}% stolen from TL/teTeX 2 | [2003/03/12 v1.1 MiKTeX 'graphics' configuration] 3 | 4 | % Select an appropriate default driver 5 | \begingroup 6 | \chardef\x=0 % 7 | % check pdfTeX 8 | \@ifundefined{pdfoutput}{}{% 9 | \ifcase\pdfoutput 10 | \else 11 | \chardef\x=1 % 12 | \fi 13 | }% 14 | \expandafter\endgroup 15 | \ifcase\x 16 | % default case 17 | \ExecuteOptions{dvips}% 18 | \else 19 | % pdfTeX is running in pdf mode 20 | \ExecuteOptions{pdftex}% 21 | \fi 22 | 23 | % Fix for dvips and xdvi versions that can uncompress 24 | % graphic files without an explicite call of gunzip. 25 | % (The fix is not applied for miniltx.tex, because 26 | % \AtEndOfPackage is not available in plainTeX.) 27 | \endinput 28 | -------------------------------------------------------------------------------- /03_shortideas/ideas/03_10_GCDnodiv.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | {\newcommand{\GCD}{\mbox{НОД}} 5 | \lheader{НОД без деления} 6 | Я надеюсь, вы все представляете, как считать НОД двух чисел алгоритмом Евклида. На всякий случай 7 | напомню: пусть вам надо посчитать $\GCD(a,b)$. Если $b=0$, но $\GCD(a,b)=a$, иначе $\GCD(a,b)=\GCD(b, a \bmod b)$. 8 | Получаем следующий алгоритм: 9 | 10 | \begin{codesampleo}\begin{verbatim}function gcd(a,b:integer):integer; 11 | begin 12 | if b=0 then 13 | gcd:=a 14 | else gcd:=gcd(b,a mod b); 15 | end;\end{verbatim} 16 | \end{codesampleo} 17 | 18 | Можно показать, что этот алгоритм работает за $O(\max(\log a,\log b))$. В частности, поэтому имеет 19 | смысл поставить задачу поиска НОД \textit{длинных} чисел. Но, как только вы глянете на приведённый 20 | выше код, сразу поймёте, что написать такое будет весьма нетривиально и неприятно. Действительно, 21 | кому охота реализовывать деление длинного на длинное (для mod)? 22 | 23 | Но есть способ посчитать НОД без деления. Точнее, без деления длинного на длинное. А именно, 24 | применим ту же идею, что применяли для быстрого возведения в степень. Посмотрим на остатки $a$ и 25 | $b$ по модулю 2. Возможны четыре случая: 26 | \begin{ulist} 27 | \item $a \bmod 2=b\bmod 2=0$. Тогда очевидно, что $\GCD(a,b)=2\cdot\GCD(a/2,b/2)$. 28 | \item $a\bmod 2=0$, но $b\bmod 2=1$. Тогда $\GCD(a,b)=\GCD(a/2,b)$. 29 | \item $a\bmod 2=1$, и $b\bmod 2=0$. Догадайтесь сами :) 30 | \item $a\bmod 2=b\bmod 2=1$. Тогда $\GCD(a,b)=\GCD(|a-b|,b)$ типа того (модуль для того, чтобы 31 | числа оставались положительными; может быть, можно и без него. Можно обойти эту проблему и как"=нибудь по"=другому...). 32 | \end{ulist} 33 | 34 | \task|Докажите все эти утверждения.||||| 35 | 36 | Этот алгоритм тоже работает за $O(\max(\log a,\log b))$, т.к. каждый вариант, кроме последнего, 37 | уменьшает хотя бы одно из чисел в 2 раза, и не бывает так, чтобы два раза подряд получился 38 | последний вариант (почему? :)), поэтому 39 | как минимум каждая вторая итерация будет уменьшать хотя бы одно из чисел в два раза. 40 | 41 | Но главное "--- здесь надо уметь делить только на два. Надеюсь, написать длинное деление и 42 | вычисление остатка по модулю два для вас элементарно :). 43 | 44 | }%newcommand -------------------------------------------------------------------------------- /03_shortideas/ideas/03_11_quicksearch.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | 5 | \lheader{Быстрый линейный поиск} 6 | Задача: дан массив $a$ из $n$ чисел (произвольный, т.е. в частности не обязательно отсортированный), 7 | требуется найти в нем заданное число $k$ или сообщить, что его в массиве нет. Тупое решение: 8 | \begin{codesampleo}\begin{verbatim} 9 | ans:=0; 10 | for i:=1 to n do 11 | if a[i]=k then begin 12 | ans:=i; 13 | break; 14 | end; 15 | \end{verbatim} 16 | \end{codesampleo} 17 | или что"=нибудь подобное. 18 | 19 | Посмотрим, сколько времени оно занимает. $O(n)$, конечно, и ясно, что быстрее не получится, 20 | т.к. надо каждый элемент массива просмотреть хотя бы раз. Но поинтересуемся константой в 21 | $O$-обозначении. На одну итерацию цикла наша программа расходует одно сравнение в if, и "--- 22 | внимание "--- одно сравнение в for (сравнивая $i$ с $n$); кроме того, одно увеличение $i$ на 23 | единицу и одно обращение к элементу массива. 24 | 25 | Обращение к элементу массива можно убрать стандартным приёмом "--- работой с указателями, я 26 | про это напишу чуть ниже. А пока обращу внимание на основное, что хочу тут написать: можно 27 | убрать и одно из двух сравнений! А именно, напишем так: 28 | \begin{codesampleo}\begin{verbatim} 29 | ans:=0; 30 | a[n+1]:=k; 31 | while a[i]<>k do 32 | inc(i); 33 | if i<>n+1 then 34 | ans:=i; 35 | \end{verbatim} 36 | \end{codesampleo} 37 | 38 | (if вне цикла тут). 39 | 40 | Я добавляю в $a[n+1]$ дополнительный элемент, как раз равный тому, что ищу. И теперь 41 | проверять, не кончился ли массив, мне не надо "--- как только массив кончится, я тут же 42 | "<найду"> этот специально поставленный элемент. Теперь в цикле на одно сравнение меньше. 43 | Только не забудьте, что здесь требуется, чтобы в массиве было место под этот дополнительный 44 | элемент (т.е. чтобы обращение к $a[n+1]$ не породило бы range check error). 45 | 46 | Можно и избавиться от обращения к элементу массива (это ведь умножение, что может тормозить, хотя 47 | это есть умножение на размер элемента массива, который чаще всего является степенью двойки и потому 48 | если компилятор умный, то умножение будет работать быстро. Умный ли компилятор в FP/Delphi, не знаю). 49 | Действительно, нам ведь надо смотреть элементы \textit{последовательно}, т.е. можно было бы 50 | завести указатель и просто его последовательно увеличивать. К моему некоторому удивлению, синтаксис 51 | паскаля (и FP, и Delphi) позволяет проделывать такие финты: 52 | \begin{codesample}\begin{verbatim} 53 | var a:array[1..maxN] of integer; 54 | p:^integer; 55 | ... 56 | a[n+1]:=k; 57 | p:=@a; 58 | while p^<>k do 59 | inc(p); 60 | ... 61 | \end{verbatim} 62 | \end{codesample} 63 | 64 | Вроде должно работать. Что я тут делаю. Есть указатель $p$ на текущий элемент массива. Изначально я 65 | кладу в него адрес $a$, т.е. фактически первого элемента $a$. Команда inc, оказывается, умеет 66 | увеличивать указатель как раз на размер соответствующего типа, т.е. в данном случае сдвигать его к 67 | следующему элементу массива. Поэтому этот код работает. Правда, не очень тривиально тут будет 68 | получить \textit{номер} найденного элемента (можно, конечно, параллельно с $p$ увеличивать ещё 69 | какую"=нибудь переменную, но это не интересно, т.к. затормозит программу: сейчас у нас в цикле пара 70 | обращений по адресу, сравнение и inc, что очень быстро. Дополнительный inc может несколько 71 | затормозить программу). Можно посмотреть на значение указателя как \verb|integer|, используя 72 | конструкцию \verb|absolute|... 73 | -------------------------------------------------------------------------------- /03_shortideas/ideas/03_13_period/rho.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_13_period/rho.eps -------------------------------------------------------------------------------- /03_shortideas/ideas/03_14_names.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \lheader{О названиях переменных, отступах и т.д.} 5 | На самом деле это отдельный сложный вопрос, и большинство в этой теме "--- это вопрос привычки и вкуса. Поэтому не смотрите на это как на обязательные требования, а просто как на какие-то идеи "--- вдруг что полезное для себя узнаете. 6 | 7 | Текст (как и некоторые другие разделы этой части) написан сначала Оксаной Побуринной (О.П.), 8 | потом потом подредактирован мною (П.К.) Большие примечания я писал в скобках, 9 | но и делал мелкие правки без указания, что это я поправил. Если в других частях я мог 10 | редактировать текст так, чтобы не приходилось явно писать, где что я добавил, то тут не так, 11 | поскольку очень многое тут есть вопрос вкуса. 12 | 13 | У каждого человека свой стиль написания программы, свои названия переменных, отступы и т.д. Но, во"=первых, 14 | нужно, чтобы этот стиль почти не менялся от программы к программе, а во"=вторых, есть неписаные общепринятые 15 | правила, которых лучше придерживаться. 16 | 17 | \textbf{1.} По поводу названий переменных. 18 | 19 | Во"=первых, полезно привыкнуть в разных программах одно и 20 | то же называть одними и теми же 21 | именами. Т.е. если вы привыкли, что $i$, $j$, $k$ "--- это переменные для циклов, $res$ или $ans$ "--- это ответ на задачу, 22 | $cur$, $t$ "--- это некое текущее значение, то по возможности так везде и пишите. Это вам поможет, 23 | чтобы 1. не думать при написании новой программы, как какую переменную назвать; 2. когда вы глядите на 24 | программу, вам будет намного проще вспомнить, что какая переменная обозначает. 25 | 26 | Во"=вторых, называйте и используйте переменные так, чтобы вам в них не запутаться. Если массивов 27 | много, не надо называть их $a$, $b$, $c$, $d$, $e$ и $f$. Не 28 | поленитесь и напишите $cost$, $color$, $was$ и т.д. Конечно, придумывать длинные названия тоже не 29 | надо, надо почувствовать баланс. Если у вас всего один массив, то напишите $a$ и не беспокойтесь. 30 | Если два, то не нужно придумывать $IsVertexVisited$ или $VertexLastVisitedTime$, если хватит просто 31 | $vis$ и $ltime$. Если у вас огромное множество переменных, то, конечно, никуда от фраз вида 32 | \begin{codesampleo}\begin{verbatim} 33 | if (Client[i].status=_free)and(not IsPinging(Client[i].sock)) then begin 34 | или 35 | pALLshutDownAnswer=^tALLshutDownAnswer; 36 | \end{verbatim} 37 | \end{codesampleo} 38 | \noindent не денешься. Но это в больших приложениях, в олимпиадных задачах такого, как правило, не бывает. (полабзаца 39 | добавлены мною "--- П.К.) 40 | 41 | Если у вас все"=таки 4 массива $a$, $b$, $c$, $d$, 42 | и вы очень хорошо помните, что $n$ "--- размер массива $a$, $m$ "--- размер $b$, $k$ "--- размер 43 | $c$ и $l$ "--- размер $d$, то пожалуйста, пишите. Только ещё раз подумайте, действительно ли вы так 44 | хорошо все помните. А лучше как минимум вместо $n$, $m$, $k$ и $l$ написать $na$, $nb$, $nc$ и $nd$ (хотя мне 45 | это тоже не очень нравится) (\textsl{Да, мне тоже. Потому что нечего называть массивы $a$ \dots{} 46 | $d$. Назовите массивы по их смыслам "--- хотя бы $w$ если это вес, $name$ если это имя и т.п. "--- 47 | и тогда пишите хотя бы $nw$, $nname$ и т.п.. Хотя все равно нечасто бывают массивы разной длины в одной программе. "--- 48 | П.К.}) 49 | 50 | Ещё полезно завести себе переменную для обмена "--- такую, которая вряд ли понадобится где-нибудь ещё 51 | (я лично всегда пишу $ex$ и не думаю, какие из переменных $a$, $b$, $c$, $aa$, $ii$, $jj$, $s$, 52 | $p$, $q$, $w$ мне не жалко для строчки $ex:=a[i]; a[i]:=a[j]; a[j]:=ex;$ "--- \textsl{А я редко 53 | пишу обмен где-нибудь, кроме как внутри процедур сортировки, в этих процедурах не так много 54 | переменных, но все равно завожу специальную $t$ "--- П.К.}) 55 | Если в коде много обменов разных типов, то можно и так сделать: вместо \texttt{var s:array [1..100] 56 | of string;} написать 57 | \begin{codesampleo}\begin{verbatim} 58 | var s:array [0..100] of string; 59 | ... 60 | s[0]:=s[i]; s[i]:=s[j]; s[j]:=s[0]; 61 | \end{verbatim} 62 | \end{codesampleo} 63 | Т.е. завести дополнительный элемент в массиве и использовать его для обмена. Это гораздо приятнее, чем заводить 64 | 5 новых переменных ради одной"=единственной строчки в коде. \textsl{(Вообще, не жадничайте и не используйте одну и туже переменную в существенно разных целях "--- если у вас нет проблем с памятью, конечно. Если вам нужна временная переменная в отдельном куске программы, не думайте, какая из переменных $i$, $j$ и т.д. у вас не занята тут, а выделите новую переменную. "--- П.К.)} 65 | 66 | Также не помешает использовать одни и те же имена для массивов в алгоритмах на графах. В частности, для поисков в глубину и 67 | ширину "--- хранить, были мы в вершине или нет: например, логические массивы $vis[i]$, 68 | $visited[i]$, $was[i]$ и т.п. Тут тоже есть проблема "--- часто нужно больше, чем 2 значения был/не 69 | был: например, в поиске в глубину и ориентированном графе или в поиске в ширину, если нам нужно 70 | помнить, за сколько шагов мы дошли до вершины и т.п. Тут можно завести массив $c$ (если он больше нигде не 71 | нужен), $col$ или $color$ для поиска в глубину, массив $d$, $dist$ расстояний для поиска в ширину 72 | (\textsl{Я не люблю логические массивы: слова true и false больно уж длинные "--- и потому даже в 73 | случае, когда значений надо всего два, использую массив целых чисел. И пишу в условии 74 | \texttt{if was[i]<>0}. "--- П.К.}) 75 | 76 | Ещё придумайте себе какое-нибудь имя для бесконечности и тоже пишите его одинаково: $INF$, $inf$, $infinity$. 77 | (\textsl{Ну, конечно, если надо для неё особое имя. Например, в качестве вещественной бесконечности 78 | я обычно использую $1e20$, и не морочусь с заведением константы для него. Не очень правильно (а 79 | вдруг придётся её изменять), но эффективно. "--- П.К.}) 80 | 81 | Ну и ещё немного. Если раньше написать процедуры nod, nok и poisk было нормально, то сейчас так не модно :) 82 | Обычно все-таки пишут по-английски, а не транслитом. 83 | 84 | Ещё замечание от меня "--- П.К. Если замечаете, что часто перепутываете, как назвать ту или иную 85 | переменную, выберите один вариант и возьмите в привычку всегда его придерживаться. Два примера: первое: как 86 | называть массив, например, имён: name или names? Хорошо звучит \texttt{var names:array... of string}: <<\textit{имена "--- 87 | массив строк}>>. Но потом \texttt{names[i]:=} звучит коряво: <<\textit{имена $i$-ое присвоить}>>. Поэтому 88 | я для себя решил, что всегда в таких случаях пишу без конечного $s$. Ещё пример: как назвать 89 | наибольшую координату: $maxx$ или $xmax$? Я так и не решил для себя, а зря. Неприятно бывает, когда 90 | написал программу и первый раз компилишь её, обнаружить, что в половине мест написал $maxx$, а в половине 91 | $xmax$\dots 92 | 93 | \textbf{2.} Про отступы. Стиль, конечно, у каждого свой, но писать без отступов точно не надо. Это крайне затрудняет чтение 94 | кода и поиск ошибок. На сколько делать отступ "--- решать вам. Но имхо лучше делать постоянный, например, всегда 1, 95 | всегда 2 и т.д., а табуляция в паскале таким постоянством не отличается. (\textsl{А мне наоборот 96 | паскалевский стиль отступов нравится больше "--- П.К.}) 97 | Отступ размера 1, мне кажется, маловат: пусть у нас много вложенных циклов 98 | \begin{codesampleo}\begin{verbatim} 99 | for i:=1 to n do begin 100 | for j:=1 to m do begin 101 | for ... begin 102 | //тут много строк кода 103 | end; 104 | //тут много строк кода 105 | end; 106 | //тут много строк кода 107 | end; 108 | \end{verbatim} 109 | \end{codesampleo} 110 | Когда begin и end далеко друг от друга, то очень плохо видно, какой end какому begin соответствует. (В принципе, 111 | это же иногда верно для отступа 2, но в гораздо меньшей степени. Я обычно делаю отступ 2, и меня вполне 112 | устраивает). Имхо, нормальные отступы "--- 2 или 3. 4 уже много "--- 3 вложенных цикла сильно сдвигают код вправо, 113 | что опять же неудобно (особенно если в борланде писать, а не в фаре "--- в фаре"=то терпимо ещё более"=менее). 114 | Опять же надо сказать, что размер отступа зависит от языка программирования. (Например если писать на java 115 | где-нибудь на работе, когда нельзя переменные называть $a$, $b$, $c$, а нужно писать так, чтобы было понятно, что они 116 | обозначают, то на фоне функций типа \texttt{Database.Fields.NumberOfDocuments.toString} отступ на 2 символа вообще 117 | незаметен :) ) 118 | 119 | Опять же непонятно, как и где именно делать отступ. Вот примеры: 120 | 121 | \begin{codesample}\begin{verbatim} 122 | for i:=1 to n do 123 | begin 124 | //чего-нибудь 125 | // 126 | end; 127 | 128 | for i:=1 to n do 129 | begin 130 | //чего-нибудь 131 | // 132 | end; 133 | 134 | for i:=1 to n do 135 | begin 136 | //чего-нибудь 137 | end; (но это вроде совсем изврат:) так писать не стоит) 138 | (собственно, предыдущее тоже изврат имхо --- П.К.) 139 | 140 | for i:=1 to n do begin 141 | //чего-нибудь 142 | end; (это как пишу я-О.П. и я-П.К. :) :) 143 | \end{verbatim} 144 | \end{codesample} 145 | 146 | Как последний вариант, тоже писать нехорошо (\textsl{а имхо самый нормальный способ "--- П.К.}), но просто мне 147 | не нравится писать begin в отдельной строчке "--- когда много циклов, это сильно удлиняет прогу, и 148 | на экран влезает гораздо меньше. 149 | 150 | \textbf{3.} Кстати, как правильно где-то было сказано, \textit{однотипность} отступов, имён и т.д., намного важнее чем сами отступы и т.д. Т.е. если вы редактируете чужую программу, и в ней отступы/пробелы сделаны не так, как вам нравится, то лучше оставить так, как там сделано, и свой код писать в соответствии с теми отступами. И, конечно, если вы пишите свою программу, то тоже стоит все делать однотипно. -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/dos.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/dos.bmp -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/dos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/dos.png -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/koi.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/koi.bmp -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/koi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/koi.png -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_dos.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_dos.bmp -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_dos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_dos.png -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_koi.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_koi.bmp -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_koi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_koi.png -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_utf16.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_utf16.bmp -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_utf16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_utf16.png -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_utf8.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_utf8.bmp -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_utf8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_utf8.png -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_win.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_win.bmp -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/rustext_win.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/rustext_win.png -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/utf8_contact.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/utf8_contact.bmp -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/utf8_contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/utf8_contact.png -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/win.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/win.bmp -------------------------------------------------------------------------------- /03_shortideas/ideas/03_1_encodings/win.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/03_shortideas/ideas/03_1_encodings/win.png -------------------------------------------------------------------------------- /03_shortideas/ideas/03_2_Axor32.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \lheader{\texttt{'A' xor ' '='a'}} 5 | Ещё одно замечание, имеющее непосредственное отношение к кодировкам, но не к основным идеям 6 | предыдущего параграфа. Обратите внимание, как расположены английские маленькие и заглавные буквы в 7 | таблицах кодировок, приведённых в предыдущем параграфе. Они расположены друг под другом. Этот 8 | обозначает, во"=первых, что их коды отличаются на 32, но ещё и, во"=вторых, что у всех заглавных 9 | букв в разряде, соответствующем степени $2^5=32$, в двоичной записи кода стоит 0, а у маленьких "--- 1. Учитывая, 10 | что 32 "--- это код пробела, это обозначает, что \texttt{'A' xor ' '='a'} (на самом деле здесь, 11 | конечно, имеются ввиду коды букв, т.е. \verb|ord('A') xor ord(' ')=ord('a')|; паскаль вам ругнётся 12 | на предыдущей строчек. Если вы не понимаете, что значит тут операция \verb|xor|, то посмотрите один 13 | из далее идущих параграфов). Это замечание, конечно, позволяет очень быстро инвертировать регистр у 14 | английского текста, но все равно не даёт широких возможностей для практического применения: даже 15 | для того, чтобы инвертировать регистр у текста, который может содержать, помимо английских букв, 16 | ещё и другие символы, надо каждый символ проверять, является ли он английской буквой, что сводит на 17 | нет всю красоту инвертации регистра таким способом; аналогичные проблемы будут, если надо, 18 | например, перевести весь текст в верхний регистр. 19 | 20 | \note{Если вам надо перевести текст в верхний регистр, то лучше воспользуйтесь встроенными функциями, 21 | либо просто прибавляйте/вычитайте 32; тем не менее имхо сам факт красив.} 22 | -------------------------------------------------------------------------------- /03_shortideas/ideas/03_3_types.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \lheader{Нетривиальные типы данных в паскале} 5 | 6 | \textbf{Вещественные типы.} Как известно, в паскале есть 4 "<настоящих"> вещественных типа: 7 | real, single, double и extended (про comp разговор будет ниже). Из них последние три "--- 8 | стандартные типы, они поддерживаются математическим сопроцессором, который, насколько я понимаю, 9 | давно встроен во все современные процессоры. А первый (real) в Borland Pascal обрабатывался 10 | полностью программно, из процессорных функций используя, 11 | видимо, только работу с целыми числами; в современных версиях это как правило или single или 12 | double, в зависимости от настроек (а, возможно, при определенных настройках это может быть и старый странный тип). 13 | 14 | Как итог, в других языках программирования есть типы, полностью совпадающие 15 | по структуре с signle и double (float и long float в C/C++, насколько я понимаю), и могут быть 16 | типы, полностью совпадающие с extended (типа long long float в некоторых компиляторах C/C++). 17 | Это, правда, нам будет фактически не 18 | важно, оно лишь приводит к тому, что, передавая, например, число типа single напрямую как оно записано в 19 | памяти "--- четырьмя байтами "--- в другую программу, вы без проблем сможете работать с ним там, 20 | даже если другая программа написана на другом языке, а вот с real не все так просто, надо понимать, какой именно это тип , "--- но такая 21 | необходимость в олимпиадных задачах возникает очень редко. 22 | Аналогично, \texttt{file of single} (см. ниже) можно читать программой, написанной на любом (ну... 23 | почти любом "--- ещё бывают проблемы с порядком байт) языке программирования, а с \texttt{file of 24 | real} все сложнее. 25 | 26 | Но все равно даже сам факт того, что real это либо single, либо double, либо что-то еще, делает тип real некоторым "<искусственным 27 | включением"> в системы типов. Это неудивительно: насколько я понимаю, во времена создания паскаля 28 | далеко не все компьютеры оснащались сопроцессором (да и, возможно, не было общепринятых стандартов 29 | хранения вещественных чисел в памяти), и потому был изобретён новый тип, чтобы можно было работать 30 | с вещественными числами и без сопроцессора. В современных же условиях нет необходимости так 31 | хитрить, и потому тип real фактически не нужен, поэтому его и приравняли к single/double. Поэтому 32 | фактически \textbf{никогда} не следует использовать в своих программах этот тип, пользуйтесь лучше single, double или extended. 33 | 34 | Какой же из трёх оставшихся типов использовать? Конечно, все зависит от задачи. Операции с single 35 | выполняются довольно быстро (но тем не менее, конечно, много дольше, чем операции с целыми 36 | числами), но, как правило, точности single не хватает в олимпиадных задачах (хотя в неолимпиадных 37 | вполне может хватать). Double обычно 38 | обеспечивает достаточную точность, но работает дольше, чем single. Extended обеспечивает ещё 39 | б\'{о}льшую точность, но ценой несоразмерного увеличения времени обработки. (Ну и, конечно, типы 40 | расходуют разное число байт: single 4, double 8, extended 10.) Тем не менее я всегда 41 | использовал где можно extended, и только если начинались проблемы с памятью или временем, переходил 42 | на double или в крайнем случае single. ИМХО, как правило, в олимпиадных задачах, где требуется 43 | вещественная арифметика, обычно время и память не столь критичны, чтобы надо было от extended 44 | уходить к другим типам. 45 | 46 | Кстати, не забываем, что при работе с вещественными числами нельзя писать \verb|if a=0| и т.п., а надо работать с \verb|eps|. 47 | 48 | \textbf{Нетривиальные целочисленные типы.} Пожалуй, ограничусь просто перечислением. 49 | \begin{ulist} 50 | \item \texttt{integer}. Казалось бы, ничего особенного, но в FP он занимает 2 или 4 байта в 51 | зависимости от настроек, и хранит соответствующий диапазон чисел. Советую в FP всегда писать 52 | \verb|{$mode delphi}| (см. ниже), и не иметь проблем. Двухбайтный тип, 53 | аналогичный BP'шному integer, называется smallint (а есть ещё и однобайтный shortint, такой же, как 54 | и в BP). 55 | \item \texttt{cardinal}, он же \texttt{longword}\footnote{Тут, похоже, есть какая"=то очень тонкая 56 | разница, связанная с поведение на разных платформах и ОС, но я её не знаю}. Это беззнаковый 57 | 32-битный тип (т.е. как word относится к integer, так cardinal относится к longint). 58 | Соответственно, позволяет хранить числа от 0 до $2^{32}-1\approx 4\,000\,000\,000$. 59 | \item \texttt{int64}. Знаковый (т.е. может хранить отрицательные числа) 64-битный тип. 60 | Хранит числа от $\approx -2^{63}$ до $\approx 2^{63}$ (пишу 61 | $\approx$, т.к. там где"=то граница отличается на единицу от степени двойки, даже понятно, где). 62 | \item \texttt{comp}. Аналогично int64 знаковый 64-битный тип. Но, в отличие от int64, он, видимо, 63 | поддерживается \textit{не} самим процессором, а сопроцессором (могу и ошибаться!). Поэтому есть ряд 64 | особенностей: во"=первых, comp был доступен даже в BP, во"=вторых, 65 | компилятор считает его вещественным типом со всеми вытекающими отсюда последствиями. В т.ч. его 66 | нельзя напрямую присваивать переменным целого типа, надо делать \texttt{round} и т.п.; с ним не 67 | работает \texttt{mod} и \texttt{div}, зато работает \texttt{/}, которое "--- внимание! "--- 68 | округляет результат по правилу round: 5/3=2, если считать в comp; при выводе в файл или на экран 69 | надо писать \verb|:0:0|, иначе будет вывод в виде с плавающей точкой (\verb|2.36348e5| типа того); 70 | кроме того, при выводе могут произойти глюки: существует небольшое количество значений comp, 71 | которые даже с \verb|:0:0| выводятся с ошибкой в паре последних знаков (хотя в памяти хранится 72 | точное значение!), поэтому с ним надо быть всегда осторожным. Т.е. comp выполняет все вычисления в 73 | пределах 64-битных целых значений абсолютно точно (как и любой целочисленный тип в пределах своей 74 | области значений), но есть приколы, которые надо понимать. Поэтому не используйте comp, используйте 75 | int64! 76 | \end{ulist} -------------------------------------------------------------------------------- /03_shortideas/ideas/03_5_bitandor.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \lheader{Битовые операции} Всем известны логические операции and, or, xor, not. Они из двух 5 | boolean"=значений делают одно: $true \OR false = true$ и т.п.. Существуют аналогичные операции 6 | для \textit{чисел}, которые выполняют соответствующие действия побитово. В паскале эти действия 7 | записываются теми же операторами, что и логические. Таким образом, например, $3 \OR 5= 7$, так как 8 | $3=\dots00011_2$, а $5=\dots00101_2$, поэтому, если про-or-ить побитово (т.е. столбиком, т.е. 9 | младший бит с младшим и т.д.), то 10 | получится $\dots00111_2=7$. Аналогично $3 \AND 5 = 1$ и $3 \XOR 5 = 6$ (xor "--- исключающее ИЛИ, 11 | т.е. равно 1, только если \textit{ровно} один бит из двух равен единице, или, что то же самое, если 12 | два бита различны). 13 | 14 | С побитовым not немного хитрее: т.к. \textit{каждый} бит инвертируется, то результат зависит от 15 | того, сколько всего бит было в числе, т.е. от типа, в котором вы проводите вычисления. Например, в 16 | byte будет, видимо, $\NOT 5= 250$. 17 | 18 | \task|Поэкспериментируйте с операцией not в других типах. В частности, верно ли, что в 19 | знаковых типах (shortint, integer, longint) not может давать отрицательные значения? Должен бы.||||| 20 | 21 | Кроме этих операций, есть ещё две довольно полезных: shr и shl. Операция shr (shift-right) осуществляет 22 | сдвиг битовой записи "<вправо">\footnote{Кавычки потому, что не очень"=то ясно, где здесь право, а 23 | где лево :). Младший разряд "--- это правый или левый?} на указанное количество бит, при этом 24 | младшие биты отбрасываются (т.е. операция эквивалентна 25 | делению на степень двойки): $2=4 \SHR 1=8 \SHR 2=16\SHR 3=32\SHR 4$ (т.е. $32 \SHR 4$ "--- это 32 26 | сдвинуть на 4 бита вправо). Кроме того, $2=5\SHR 1=11\SHR 2=18\SHR 3=40\SHR 4$, и $5\SHR 4=0$, т.к. младшие биты 27 | отбрасываются. Операция shl сдвигает битовую запись влево, дополняя младшие разряды нулями (т.е. 28 | эквивалентно умножению на степень двойки). Старшие 29 | разряды, вылезающие за тип, видимо, отбрасываются. Результат, конечно же, зависит от типа. Пример: 30 | в любом типе $2\SHL 1=4$, $5\SHL 4=80$; если влезет в тип, то $1\SHL k=2^k$. 31 | 32 | \task|Поэкспериментируйте с операцией shl в других типах. В частности, верно ли, что в 33 | знаковых типах (shortint, integer, longint) shl может давать отрицательные значения? Вроде действительно может давать.||||| 34 | 35 | Огромное достоинство битовых операций состоит в том, что они выполняются \textit{очень} быстро (см. 36 | также ниже, в параграфе про скорость операций). Например, делить на два с помощью shr~1 намного 37 | быстрее, чем с помощью div 2. Это, правда, не всегда важно "--- если операций деления на два у вас 38 | не так много, то сильно программу замена div~2 на shr~1 не ускорит, но иногда может помочь (см. также там же ниже). А вот возведение 39 | двойки в степень писать как $1\SHL k$ намного проще, чем циклом, и работать будет быстрее. Только 40 | ВНИМАНИЕ: стандартная ошибка "--- написать тут 2 вместо 1: например для деления на 2 написать 41 | shr~2 по аналогии с div~2 :) вместо верного shr~1, аналогично можно случайно написать $2\SHL k$ для 42 | возведения 2 в степень $k$. Это, конечно, приведёт к неправильному результату. 43 | 44 | Битовые операции вы применяете, обычно, тогда, когда вам действительно надо что"=то сделать, 45 | связанное с битами. Например, число из $k$ единиц ($11\dots1_2$) можно получить как $1\SHL k-1$. 46 | Входит ли $k$"=я степень двойки в двоичное представление числа $n$ можно проверить так: $(n \SHR k) 47 | \AND 1=1$ или "--- второй способ "--- $n \AND (1 \SHL k)<>0$. В частности, проверить, чётно или нечётно число можно, 48 | посмотрев, чему равно $n \AND 1$, и т.п. 49 | 50 | Обратите внимание, что я везде, где надо, ставлю скобки. Т.к. запомнить порядок действий здесь я не 51 | могу, то лучше для однозначности ставить скобки. 52 | 53 | \task|Как быстро с помощью битовых операций вычислить максимальную степень двойки, на 54 | которую делится данное число? Ответ должен быть просто арифметическим выражением, без всяких циклов 55 | и т.п. и, например, для числа 40 давать ответ 8. 56 | ||Пусть нам дано число $N$. Посмотрите, чем $N-1$ отличается от $N$ в битовой записи. 57 | ||Пусть $N$ оканчивается на $k$ нулей, перед которыми идёт единица. Тогда ответ на наш вопрос будет $100\dots0_2$ "--- единица с $k$ нулями на конце. Как это вычислить? Заметим, что $N-1$ заканчивается на $k-1$ единицу, перед которыми идёт ноль (просто вычтите единицу из $N$ столбиком), т.е. отличается от $N$ ровно в $k+1$ последних битах. Тогда $N \XOR (N-1)$ будет равно $11\dots1_2$ "--- число, состоящее из $(k+1)$ единицы, "--- и $((N \XOR (N-1)) +1) \SHR 1$ даст то, что нам надо. Вообще, идея про-xor-ить $N$ и $N-1$ для выделения нулей на конце числа $N$ довольно часто встречается. 58 | | 59 | 60 | Ещё частое употребление "--- если вы числом $n$ кодируете последовательность нулей и единиц 61 | (закрашенных и незакрашенных клеток, используемых и не используемых объектов и т.п.), и вам надо 62 | что"=то с ней сделать (определить, закрашена ли та или иная клетка), то почти всегда подобные действия можно перевести на язык битовых операций. -------------------------------------------------------------------------------- /03_shortideas/ideas/03_6_fileof.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \lheader{"<Бинарный"> ввод"=вывод} Вы прекрасно знаете, как вводить/выводить данные из/в файл, в 5 | котором данные записаны/должны быть записаны plain text, т.е. чистым текстом, который, не напрягаясь, может 6 | прочитать человек: вы используете тип text и все, что с ним связано. В результате все числа в файле 7 | получаются в виде последовательности десятичных цифр и т.п. Но обратите внимание, что это весьма 8 | неэкономный способ ввода/вывода: он требует довольно нетривиальной обработки по переводу числа из 9 | того вида, как оно записан в файле, в тот вид, в котором оно хранится в памяти компьютера и 10 | используется программой, и наоборот; кроме того, числа в файле занимают намного больше места, чем 11 | могли бы (для записи значения типа integer, например, может потребоваться 5 цифр + знак + пробел, в то 12 | время как на самом деле для кодирования значения integer достаточно двух байт). Основное 13 | достоинство такого формата состоит в том, что его может без особых раздумий прочитать человек. 14 | 15 | Но бываю случаи, когда простота ввода/вывода и занимаемое место становится более важно, чем 16 | "<читабельность"> вывода. Для этого существует возможность записывать данные в файл непосредственно 17 | так, как они хранятся в памяти: если в памяти число 28454 ($={\rm6F26}_{16}$) типа integer занимает 2 18 | байта, в которые записаны значения 111 ($={\rm6F}_{16}$) и 38 ($=26_{16}$) (с точностью до порядка 19 | байт, см. ниже), то и в файле это же число займёт два байта, в которые будут записаны те же 20 | значения 6F и 26. Файлы, в которые данные записаны таким способом, часто называют "<бинарными"> (а 21 | обычные файла в этом смысле "--- "<текстовыми">), 22 | соответственно такой способ ввода/вывода можно называть "<бинарным">. В паскале такой способ 23 | ввода/вывода можно осуществлять с помощью переменных типа file и file of. 24 | 25 | \textbf{file of.} Пусть вам надо вводить/выводить в/из файла последовательность данных одного и 26 | того же типа (этот тип может быть каким угодно: как "<стандартным">, типа integer, так и "<шаблоном">, 27 | определённым через команду type, в том числе record, array и т.п.). Тогда вы можете написать, 28 | например, следующую программу: 29 | \begin{codesample}\begin{verbatim} 30 | var f:file of integer; 31 | a,b,c:smallint; 32 | 33 | begin 34 | assign(f,'input.dat');reset(f); 35 | read(f,a,b,c); 36 | close(f); 37 | end. 38 | \end{verbatim} 39 | \end{codesample} 40 | \noindent при этом из файла input.dat будут считаны первые шесть байт и напрямую записаны в память: 41 | первые два байта "--- по адресу переменной $a$, вторая пара байт "--- $b$, третья пара 42 | байт "--- $c$. 43 | 44 | Вообще, тип \texttt{file of \textit{тип}} используется для такого бинарного ввода/вывода. Команды 45 | assign и reset/\linebreak[0]rewrite имеют, видимо, тот же смысл, что и для переменных типа text (хотя я точно не 46 | знаю, будет ли ввод/вывод буферизован; по крайней мере, команду settextbuf использовать точно не 47 | получится). После этого вы можете командами read/write читать/записывать данные, но теперь уже 48 | только переменные того типа, который вы указали в конструкции file of (т.е. если вы написали file 49 | of longint "--- то только переменные типа longint). В файл будут записываться данные 50 | непосредственно так, как они хранятся в памяти и считываться в память они будут аналогично. Каждая 51 | запись/чтение одной переменной будет записывать/считывать ровно столько байт, сколько занимают 52 | переменные этого типа в памяти. Обратите внимание, что readln/writeln здесь бессмысленен, т.к. 53 | переводы строк "--- это особенности чисто текстовых файлов. 54 | 55 | Ещё раз подчеркну, что использовать тут можно любые типы "--- как стандартные, так и свои, 56 | определённые через команду type: 57 | \begin{codesample}\begin{verbatim} 58 | type tData=record 59 | a,b,c:integer; 60 | d:single; 61 | s:string[30]; 62 | end; 63 | 64 | var f:file of tData; 65 | d:tData; 66 | begin 67 | assign(f,'input.dat');reset(f); 68 | read(f,d); 69 | ... 70 | \end{verbatim} 71 | \end{codesample} 72 | 73 | или 74 | \begin{codesampleo}\begin{verbatim} 75 | type tArr=array[1..30] of integer; 76 | var f:file of tArr; 77 | \end{verbatim} 78 | \end{codesampleo} 79 | и т.п. 80 | 81 | \textbf{file.} Такой тип данных подразумевает, что файл состоит из некоторого количества 82 | "<записей">, каждая "<запись"> имеет одну и ту же длину. Длина записи (в байтах) указывается 83 | \textit{вторым параметром команд reset/rewrite}, т.е. эти команды требуют тут \textit{два} 84 | параметра. После этого единственная команда, которой можно работать с файлом "--- это blockread или 85 | blockwrite. Они принимают три параметра: переменную типа file, откуда читать/куда писать, дальше переменную 86 | \textit{любого} типа, которая указывает адрес памяти, куда/откуда писать, и количество "<записей">, которые 87 | надо прочитать/записать. Команды не выполняют \textit{вообще} никакой проверки на соответствие типов, на то, 88 | что вся память, куда/откуда вы хотите писать, действительно выделена вам и т.д. Пример: 89 | \begin{codesample}\begin{verbatim} 90 | type tData=record 91 | a,b,c:integer; 92 | d:single; 93 | s:string[30]; 94 | end; 95 | 96 | var f:file; 97 | d:array[1..10] of tData; 98 | begin 99 | assign(f,'input.dat');reset(f,sizeof(tData)); 100 | blockread(f,d,10); 101 | ... 102 | \end{verbatim} 103 | \end{codesample} 104 | 105 | Размер "<записи"> здесь делается равным размеру типа tData, поэтому команда blockread считывает 10 106 | "<записей">, тем самым как раз заполняя весь массив d. 107 | 108 | \pagebreak[3] 109 | 110 | На самом деле понятие "<записи"> не очень важно: паскаль далеко не требует, чтобы это было 111 | что"=нибудь осмысленное (например, размер элемента массива), единственный смысл этого понятия "--- 112 | на размер записи умножается третий аргумент команд blockread/blockwrite, чтобы получить количество 113 | байт, сколько надо считать. Поэтому следующие две программы равносильны и равносильны первой (с 114 | точностью до того, что эти программы записывают данные, а не считывают): 115 | \begin{codesample}\begin{verbatim} 116 | type tData=record 117 | a,b,c:integer; 118 | d:single; 119 | s:string[30]; 120 | end; 121 | 122 | var f:file; 123 | d:array[1..10] of tData; 124 | ... 125 | assign(f,'input.dat');rewrite(f,2*sizeof(tData)); 126 | blockwrite(f,d,5); 127 | ... 128 | \end{verbatim} 129 | \end{codesample} 130 | \begin{codesample}\begin{verbatim} 131 | type tData=record 132 | a,b,c:integer; 133 | d:single; 134 | s:string[30]; 135 | end; 136 | 137 | var f:file; 138 | d:array[1..10] of tData; 139 | ... 140 | assign(f,'input.dat');rewrite(f,1); 141 | blockwrite(f,d,sizeof(d)); 142 | ... 143 | \end{verbatim} 144 | \end{codesample} 145 | 146 | Обратите внимание на последнюю программу: здесь я указываю, что размер записи равен 1, и далее 147 | просто указываю количество байт, сколько надо считать. ИМХО, так делать в большинстве случаев 148 | удобнее всего: в команде reset/rewite писать 1, а в blockread/blockwrite писать точное количество 149 | байт (используя sizeof при необходимости). Если бы я захотел считать 8, а не 10 элементов (т.е. 150 | массив не полностью, то я бы написал blockread(f,d,8*sizeof(tData)). Ещё зацените следующую 151 | программу: я тут храню сначала количество элементов, а потом сами элементы: 152 | \begin{codesample}\begin{verbatim} 153 | ... 154 | var f:file; 155 | d:array[1..10] of tData; 156 | n:integer; 157 | ... 158 | assign(f,'input.dat');reset(f,1); 159 | blockread(f,n,sizeof(n)); 160 | blockread(f,d,n*sizeof(tData)); 161 | ... 162 | \end{verbatim} 163 | \end{codesample} 164 | Таким образом можно хранить в бинарном файле данные совершенно разных типов вперемешку. 165 | 166 | Ещё раз подчёркиваю, что \textit{никаких} проверок blockread/blockwrite не делает, а тупо копирует 167 | сколько указано байт. Если в последнем примере получится $n>10$, то никакого вам Range check error 168 | даже при включённом \verb'{$R+}' не будет "--- blockread просто \textit{не знает}, что ему 169 | подсунули массив из 10 элементов. Для него второй аргумент "--- это просто адрес места в 170 | памяти. 171 | 172 | Ещё пара общих замечаний (и к file, и к file of). Во"=первых, на разных системах (ОС или вообще 173 | архитектурах компьютеров) может быть разный порядок байт: число 28454 174 | может представляться в памяти как два байта 6F~26, так и как два байта 26~6F (сравните, как вы 175 | храните числа в длинной арифметике); с четырехбайтовыми числами все ещё хуже. 176 | Можете поэкспериментировать, чтобы проверить, какой порядок в 177 | Windows. Поэтому бинарный файл, записанный на одном компьютере, может не прочитаться на другом. 178 | 179 | Во"=вторых, выравнивание "--- то самое, на которое влияет ключ \verb|$A|, см. выше. Все программы, которые пишут, например, record'ы в 180 | бинарные файлы, должны учитывать возможность выравнивания: если файл записан с одними настройками выравнивания, а 181 | прочитан с другими, то это может вызвать проблемы. Я обычно в таких случаях специально ставлю ключ 182 | компилятора \verb'{$A-}', чтобы гарантированно совсем отключить выравнивание. 183 | 184 | -------------------------------------------------------------------------------- /03_shortideas/ideas/03_7_optimes.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \lheader{Время выполнения различных элементарных операций} Тут я немного скажу про время выполнения 5 | различных элементарных (т.е. арифметических и т.п.) операций. Все, что сказано в этом разделе, не 6 | влияет на \textit{сложность} алгоритмов, но очень влияет на константу в этих алгоритмах. 7 | 8 | Итак, различные арифметические операции выполняются, конечно, за различное время. Но важно 9 | понимать, что эти времена \textit{очень сильно} различаются. 10 | 11 | \taskn{Обязательное :) задание}|Напишите простую программу, которая будет считать время 12 | выполнения разных операций "--- просто выполняя их много раз подряд и считая время выполнения такого 13 | блока, примерно по следующему шаблону: 14 | \begin{codesample}\begin{verbatim} 15 | begin 16 | вывести текущее время 17 | for i:=1 to 1000000 do begin 18 | c:=a+b; 19 | c:=a+b; 20 | ... 21 | c:=a+b; 22 | end; 23 | вывести текущее время 24 | end. 25 | \end{verbatim} 26 | \end{codesample} 27 | \noindent Несколько сложений внутри цикла сделано, чтобы основное время программа тратила именно на сложение, 28 | а не на "<накладные расходы">: увеличение i и сравнение его с верхним пределом цикла. Верхний 29 | предел цикла, конечно, ст\'{о}ит подбирать, чтобы программа работала не слишком быстро (иначе таймер 30 | успеет слишком мало измениться), но и не слишком медленно (чтобы вам не надоело ждать :)), имхо 31 | оптимальное время работы порядка секунды. Обратите 32 | внимание на то, как я считаю время работы. Посмотрите, сколько времени занимает сложение/вычитание, 33 | умножение, деление (div и mod) целых чисел (на примере integer и/или longint), сколько занимают аналогичные 34 | операции с вещественными числами (можете сравнить все четыре вещественных типа: single, double, 35 | extended и real); посмотрите, сколько времени занимают shr, shl, побитовые and, or и т.д. При 36 | желании можете посмотреть, как влияет \verb'{$R+}' на время работы с массивами и т.п. Только 37 | делайте все c \textit{отключённой} оптимизацией (\verb'{$O-}'), иначе она вам 38 | такого тут наоптимизирует... 39 | ||||| 40 | 41 | А теперь приведу результаты своих исследований, которые я проводил очень давно и потому могу 42 | ошибаться (поэтому обязательно проверьте меня! :) ). Целочисленные операции: битовые операции (shr, 43 | and и т.п.) выполняются вроде примерно столько же 44 | времени, что и сложение и вычитание, но умножение выполняется на порядок (т.е. раз в 10) 45 | дольше, а деление (div и mod) "--- на два порядка (т.е. раз в сто медленнее!). С вещественными 46 | операциями картина примерно такая же: сложение/вычитание, потом умножение и наконец деление, только 47 | каждая операция, конечно же, тормознее, чем соответствующая операция с целыми числами (т.е. 48 | умножение вещественных чисел тормознее, чем умножение целых, что логично). Про времена работы 49 | разных вещественных типов я писал выше, здесь замечу ещё то, что, если я не ошибаюсь, 50 | \textit{вещественное умножение работает быстрее целочисленного деления} (и уж тем более 51 | вещественного деления). 52 | 53 | Мораль (одна из; конечно, есть и ещё морали из всего этого). Деление "--- \textit{очень} тормозное 54 | действие. Его стоит по возможности избегать. В частности, деление на степень двойки можно заменять 55 | на shr. Ещё полезная идея: если вам несколько раз подряд надо делить на \textit{одно и тоже} число $x$, то 56 | намного быстрее будет посчитать заранее обратное ему "--- $xx:=1/x;$ "--- и дальше умножать на 57 | $xx$. Эта идею можно применить и к целым числам: вместо последовательного деления 58 | (div/mod) на одно и то же число $k$ можно заранее посчитать обратное к этому числу $kk:=1/k;$ (которое, конечно, 59 | будет вещественным) и дальше вместо \verb'n div k' делать \verb'trunc(kk*n)'; аналогично можно и 60 | mod заменить на умножение. Т.к. даже вещественное умножение работает быстрее целочисленного 61 | деления, то это сработает. Ещё раз подчёркиваю, что это имеет смысл только когда вы много раз 62 | подряд делите на одно и то же число. 63 | 64 | Пример: алгоритм Гаусса решения системы линейных уравнений: там много раз подряд 65 | приходится делить на одно и то же число. Если заранее посчитать обратное к нему, и потом умножать, 66 | то алгоритм резко ускорится. Ещё пример: в длинной арифметике приходится часть делить и вычислять 67 | остаток по модулю, равному основанию системы счисления. Аналогично, тут можно заранее посчитать 68 | обратное к основанию системы счисления (причём один раз на всю программу! "--- или даже забить в 69 | const), а потом использовать умножение и trunc (или работать в системе счисления с 70 | основанием "--- степенью двойки :) ) 71 | 72 | И два финальных замечания. Первое: оптимизировать имеет смысл в первую очередь самые тормозные 73 | куски программы. Т.е., в частности, если основное время в вашей программе уходит далеко не на 74 | деление (а, например, на какой"=нибудь мощный цикл с сложениями и умножениями), то и оптимизировать 75 | деление нечего (в частности, если у вас деление выполняется всего десять раз за программу, то 76 | оптимизировать его незачем). В длинной арифметике и в алгоритме Гаусса довольно большая часть 77 | времени уходит на деление, поэтому в этих алгоритмах его оптимизировать имеет смысл. 78 | 79 | Второе, общее для любых оптимизаций, не меняющих сложности программы: как бы вы не оптимизировали 80 | деление, \textit{сложность} программы от этого не изменится. Поэтому а) если ваше решение 81 | правильное, то обычно оно и без оптимизаций пройдёт все тесты (обычно жюри не закладывается на то, 82 | чтобы участники очень уж оптимизировали программы), хотя, конечно, проверить время все равно надо, 83 | и, если не укладываетесь, то можно оптимизить, и б) если ваше решение неправильное, то оно 84 | правильным не станет, и это надо понимать (оптимизация скорее всего не поможет набрать полный балл, 85 | но общий балл может увеличить. Полный балл тоже иногда получается, но очень редко :) ). Короче, в 86 | первую очередь ищите алгоритм с более хорошей сложностью, и только во вторую очередь оптимизируйте 87 | константу в этой самой сложности. 88 | -------------------------------------------------------------------------------- /03_shortideas/ideas/03_8_changetest.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \lheader{Изменение тестов} Иногда вы можете придумать ту или иную идею решения задачи, которая 5 | будет работать почти всегда, за исключением нескольких особо подлых случаев. Например, в 6 | какой-нибудь геометрической задаче может оказаться, что три точки лежат на одной прямой, или при 7 | сортировке может обнаружится несколько одинаковых чисел и т.п. "--- и это сломает ваш алгоритм. Вероятность таких 8 | случаев может быть бесконечно мала (ясно, что если вы возьмёте три \textit{случайные} точки на 9 | плоскости, то почти наверняка они не окажутся на одной прямой), но мы ведь прекрасно знаем, что 10 | жюри вполне может подсунуть вам любую подлость. Обычно приходится что-то особенное придумывать, 11 | чтобы обработать такие случаи. 12 | 13 | Но есть одна простая идея, которая может помочь. Я её никогда практически не использовал, и использовать её 14 | надо, конечно, с осторожностью (впрочем, как и \textit{любую другую} идею: любую идею нельзя 15 | использовать слепо, всё, что вы делаете, вы должны понимать), но иногда она, возможно, может вас 16 | выручить. Идея состоит в том, чтобы немного подправить тест, в частности, подправить случайным 17 | образом. Если вы подправляете тест случайным образом, то наверняка в новом тесте не будет никаких 18 | подлых случаев (если эти подлости действительно так редки), только надо подправлять аккуратно. 19 | Сильно менять тест, конечно, нельзя "--- вы должны так изменить тест, чтобы ответ на него не 20 | изменился или изменился в пределах допустимой погрешности "--- но, с другой стороны, надо изменить 21 | тест так, чтобы ваша собственная программа заметила изменение (иначе зачем вы его меняли? :) ). В 22 | частности, в задачах с вещественными числами вы не будете сравнивать оператором =, надо сравнивать 23 | с конечной точностью "--- а тогда ваше небольшое изменение теста может оказаться незамеченным... В 24 | общем, как всегда, что бы вы ни делали, надо думать. 25 | 26 | Т.к. я сам эти идеи почти не использовал, то буду приводить те примеры, которые мне сейчас пришли в 27 | голову. Я не уверен, что все они корректны, т.е. что во всех примерах эти идеи действительно 28 | работают, но представление о том, что можно делать, вы, наверное, получите. 29 | 30 | Например, если в задаче построения выпуклой оболочки вам мешали тройки точек, лежащие на 31 | одной прямой, то, если вы перед поиском оболочки чуть"=чуть, причём случайным образом, сдвинете 32 | каждую точку, то таких троек не будет. 33 | Ещё пример, и тоже на выпуклую оболочку (так уж получилось). Если мне память не изменяет, я однажды видел такой вариант реализации выпуклой 34 | оболочки. Они брали точку на плоскости (не из 35 | тех, которые даны во входном файле), которая 36 | гарантированно будет \textit{внутри} оболочки, сортировали все точки по полярному углу относительно 37 | неё, и работали дальше. Выбрать такую точку можно было просто "--- например, как центр тяжести всех точек, но тут 38 | могли быть две подлости: во"=первых, выбранная точка могла совпасть с 39 | какой"=нибудь точкой из входного файла, во"=вторых, выбранная точка могла случайно оказаться на 40 | прямой, соединяющей какие"=нибудь две точки из входного файла. Оба этих случая были бы проблемами 41 | для их алгоритма, их надо было бы обрабатывать особо. Поэтому они давали каждой точке из 42 | входного файла случайный вес и считали центр тяжести таких взвешенных точек. За счёт случайности 43 | весов никаких таких подлостей не могло быть. Обратите внимание, кстати, что эта идея никак не 44 | портит сам тест, т.е. ответ на тест все равно точно получится правильный. Это аналогично выбору 45 | \textit{случайного} разделительного элемента в QSort'е. Этот пример я привожу не для того, чтобы 46 | сказать, что именно так и надо писать выпуклую оболочку "--- никак нет, её надо писать не так "--- но для того, чтобы вы поняли, что random можно активно использовать, 47 | даже не обязательно вредя тесту. 48 | 49 | И ещё пример. Была задача типа такой: на плоскости задано $N$ прямоугольников. Человеку надо пройти 50 | из точки $A$ в точку $B$, не заходя внутрь прямоугольников. При этом он может пролезать в щели 51 | сколько угодно маленькой, \textit{но ненулевой}, ширины. При написании программы у меня возникла 52 | проблема именно с этой ненулевостью. Было довольно нетривиально допустить любые щели, но не 53 | допустить нулевых. Потому я просто чуть"=чуть расширил каждый прямоугольник, так, чтобы бывшие нулевые щели 54 | стали вообще закрытыми (прямоугольники будут накладываться), а любые остальные щели остались бы 55 | ненулевыми. Не помню, по"=моему, у меня программа не получила полный балл по каким"=то другим 56 | причинам, но идея расширения мне нравится до сих пор. 57 | 58 | В общем, основная идея этой темы "--- что различные подлые случаи можно обрабатывать особо, а можно 59 | пытаться их избежать. Можно думать в этом направлении. Думайте, изобретайте. -------------------------------------------------------------------------------- /03_shortideas/ideas/03_9_quickpow.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \lheader{Быстрое возведение в степень и умножение} 5 | Пусть нам надо число $a$ возвести в степень $p$ или умножить на число $p$ (примеры кода для 6 | умножения и возведения буду приводить параллельно в двух колонках; число $p$ должно быть 7 | натуральным, а $a$ может быть произвольным). Для задачи возведения в степень будем считать, что мы умеем 8 | только умножать, для задачи умножения будем считать, что мы умеет только складывать (на самом деле 9 | задачу про умножение я привожу тут только для понятности "--- мне кажется, её понять может быть проще. В 10 | реальности я не представляю случая, когда вам пришлось бы так умножать). Основной текст будет про 11 | возведение в степень, только примеры буду приводить параллельно для обеих задач. 12 | 13 | Конечно, можно сделать это тупо, написав что-нибудь вроде: 14 | 15 | \begin{codesample}\begin{verbatim} 16 | ans:=1; {в этой переменной будем хранить ответ} 17 | for i:=1 to p do ans:=ans*a; 18 | ans:=0; {в этой переменной будем хранить ответ} 19 | for i:=1 to p do ans:=ans+a; 20 | \end{verbatim} 21 | \end{codesample} 22 | 23 | К сожалению, этот цикл выполняется за $O(p)$. Если $p$ маленькое, то можно (и нужно!) не мучиться и написать этот простой цикл 24 | (ведь любое усложнение программы повышает вероятность ошибки). Если же $p$ большое, или же $p$ 25 | "<среднее">, но возводить в степень придётся много раз, то лучше делать все за $O(\log p)$ (ясно, что, если $p$ совсем маленькое, то в 26 | любом случае надо писать по"=тупому). Этот метод на самом деле интуитивно понятен. Если вам нужно посчитать $6^8$, то можно просто $6$ 27 | возвести в квадрат, потом ещё раз в квадрат, потом ещё раз в квадрат. Эту идею мы будем использовать в нашем алгоритме. 28 | 29 | Пусть нам надо посчитать $a^{43}$. Разложим $43$ по степеням двойки: $43 = 32 + 8 + 2 + 1$. Тогда 30 | $a^{43} \hm= a^1 \cdot a^2 \cdot a^8 \cdot a^{32}$. Будем в переменной $t$ считать $a^1$, потом $a^2$, 31 | $a^4$, $a^8$, $a^{16}$ и т.д. (просто последовательно возводя $t$ в квадрат) и постепенно 32 | умножать на некоторые из них (на те, которые нам нужны) текущий результат. Как проверить, 33 | какие степени нам нужны? Очень просто, см. в части II текущей темы :) про побитовые операции. 34 | Степень $a^{2^i}$ нам нужна тогда и только тогда, когда $p \AND 2^i \neq 0$. 35 | 36 | {\small Аналогично для умножения: например, $43a=32a+8a+2a+1a$, в переменной $t$ будем 37 | последовательно считать $1a$, $2a$, $4a$, $8a$ и т.д. путём последовательного сложения $t$ с собой; 38 | необходимые числа будем добавлять к ответу. 39 | 40 | } 41 | 42 | \begin{codesample}\begin{verbatim} 43 | ans:=1; 44 | t:=a; 45 | cp:=1; {текущая степень, т.е. t=a^(2^cp)} 46 | while 1 shl cp

0 then ans:=ans*t; 48 | t:=t*t; 49 | inc(cp); 50 | end; 51 | ans:=0; 52 | t:=a; 53 | cp:=1; {t=a*(2^cp)} 54 | while 1 shl cp

0 then ans:=ans+t; 56 | t:=t+t; 57 | inc(cp); 58 | end; 59 | \end{verbatim} 60 | \end{codesample} 61 | (Немного про условие $1 \SHL cp0 do begin 79 | if p and 1 = 1 then ans:=ans*t; 80 | p:=p shr 1; 81 | t:=t*t; 82 | end; 83 | ans:=1; 84 | t:=a; 85 | while p>0 do begin 86 | if p and 1 = 1 then ans:=ans+t; 87 | p:=p shr 1; 88 | t:=t+t; 89 | end; 90 | \end{verbatim} 91 | \end{codesample} 92 | 93 | Код совсем несложный, главное "--- чётко понимать, что вы делаете и что тут происходит :) 94 | Понять корректность этого кода можно и следующим образом. Заметим, что в каждый 95 | момент у нас будет верно, что $(ans\cdot t^p)$ равно требуемому ответу (так называемый 96 | "<инвариант цикла">). Действительно, изначально $ans=1$, 97 | $t=a$, а $p$ ещё не менялось, поэтому $ans\cdot t^p=t^p$ как раз и есть то, что мы и хотим 98 | получить. Далее, на очередном шаге есть два варианта: если $p$ чётное, то 99 | $ans\cdot t^p=ans\cdot (t^2)^{(p/2)}$, т.е. можно просто поделить $p$ на 2 и возвести $t$ в квадрат, при 100 | этом инвариант не нарушится. Если же $p$ нечётное, то "<отщепим"> от $p$ единицу: 101 | $ans\cdot t^p=(ans\cdot t)\cdot (t^2)^{(p/2)}$ (деление пополам тут имеется ввиду в смысле 102 | div~2, или shr~1, т.е. с сохранением только целой части). В конце концов, когда $p$ станет равно 0, получится, что 103 | искомый ответ равен $ans\cdot t^p=ans\cdot t^0=ans$, т.е. он уже лежит в переменной $ans$. 104 | Фактически, мы как бы "<перелили"> множители из $t^p$ в $ans$. 105 | 106 | Нетрудно видеть, что цикл работает за $O(\log p)$, т.к. каждый раз число $p$ уменьшается хотя бы 107 | в два раза (ровно в два раза, когда на конце нолик, и чуть больше, чем в два раза, когда единичка). 108 | 109 | Дальнейшие рассуждения имеют смысл в первую очередь именно для возведения в степень, а не умножения. 110 | Как уже было сказано выше, данный код имеет смысл писать, когда число $p$ большое. Но тогда $a^p$, 111 | скорее всего, не влезет ни в какую память, даже в extended, int64 и т.д. Конечно, может стоять 112 | задача вычисления степени длинной арифметикой, но тут "--- внимание! "--- приведённый алгоритм 113 | не столь эффективен, т.к. требует умножения \textit{длинного на длинное}, в то время как тупой 114 | алгоритм требует лишь умножения \textit{длинного на короткое} (можете попробовать оценить сложности 115 | обоих алгоритмов, учитывая, что в ответе будет $O(p)$ цифр; у меня получилась сложность $O(p^2)$ 116 | для тупого алгоритма и $O(p^2\log p)$ для "<продвинутого">, т.е. "<продвинутый"> в этом случае "--- 117 | при использовании длинной арифметики "--- даже хуже простого). 118 | 119 | Но нередко бывает нужно вычислить ответ только по некоторому (большому, но лезущему в longint и т.п.) модулю $inf$, т.е. 120 | вычислить $a^p \bmod inf$ (от слова infinity "--- бесконечность:) ). Это, пожалуй, и есть как раз 121 | самый основной случай применения этого алгоритма. 122 | 123 | \begin{codesampleo}\begin{verbatim} 124 | ans:=1; 125 | t:=a; 126 | while p>0 do begin 127 | if p and 1 = 1 then ans:=(ans*t) mod inf; 128 | p:=p shr 1; 129 | t:=(t*t) mod inf; 130 | end; 131 | \end{verbatim} 132 | \end{codesampleo} 133 | 134 | Тут, конечно, надо быть осторожным: если хранить все переменные в лонгинте, а $inf\sim 10^9$ (т.е. 135 | порядка $10^9$), то во время умножения $ans*t$ или $t*t$ может произойти переполнение; надо 136 | подумать, что с ним делать. 137 | 138 | Ну и ещё один комментарий: это как раз тот случай, когда надо писать shr~1, а не div~2, как и 139 | написано везде выше. 140 | -------------------------------------------------------------------------------- /03_shortideas/problems.cls: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e} 2 | \ProvidesClass{problems}[2006/11/03] 3 | 4 | % identification 5 | % initial code 6 | % declaration of options 7 | % execution of options 8 | % package loading 9 | % main code 10 | 11 | % Declaration of Options 12 | \DeclareOption{draft}{\PassOptionsToClass{draft}{article}\AtEndOfClass{\geometry{showframe}}} 13 | \DeclareOption{10pt}{\PassOptionsToClass{10pt}{article}} 14 | \DeclareOption{11pt}{\PassOptionsToClass{11pt}{article}} 15 | \DeclareOption{12pt}{\PassOptionsToClass{12pt}{article}} 16 | 17 | \hfuzz=0.1cm 18 | 19 | % Опцию a4paper будем использовать для формата, в котором задачки 20 | % печатались раньше на бумаге A4. 21 | \DeclareOption{a4paper}{ 22 | \PassOptionsToPackage{a4paper,includehead,includefoot,headheight=10pt,headsep=2mm,width=17cm,height=27cm,footskip=0.5cm}{geometry} 23 | } 24 | 25 | % Execution of Options 26 | \ProcessOptions\relax 27 | 28 | % Package Loading 29 | \LoadClass[a4paper]{article} 30 | 31 | \RequirePackage[T2A]{fontenc} 32 | \RequirePackage[utf8]{inputenc} 33 | \RequirePackage{mathtext} 34 | \RequirePackage[english,russian]{babel} 35 | \RequirePackage[dvips,final]{graphicx} 36 | \RequirePackage{wrapfig} 37 | \RequirePackage{amssymb} 38 | \RequirePackage{amsmath} 39 | \RequirePackage{amscd} 40 | \RequirePackage{array} 41 | \RequirePackage{multicol} 42 | \RequirePackage{longtable} 43 | \RequirePackage[dvips]{geometry} 44 | 45 | % Main Code 46 | \columnseprule=0.4pt 47 | \raggedbottom 48 | 49 | 50 | % AK: думаю, лучше везде использовать вариант "". 51 | %\declare@shorthand{russian}{""}{\nobreak\hskip.2em\ignorespaces} 52 | %\declare@shorthand{russian}{",}{\nobreak\hskip.2em\ignorespaces} 53 | % KAP: чтобы кавычки всегда были правильные 54 | %\declare@shorthand{russian}{"<}{<<} 55 | %\declare@shorthand{russian}{">}{>>} 56 | %---------- From package "lastpage" ------------------ 57 | \def\lastpage@putlabel{\addtocounter{page}{-1}% 58 | \immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}% 59 | \addtocounter{page}{1}} 60 | \AtEndDocument{\clearpage\lastpage@putlabel}% 61 | %---------- end of "lastpage" ------------------ 62 | 63 | \newcommand{\headernono}[1]{% 64 | \par\vspace*{1.5ex plus7ex minus .7ex}\pagebreak[3]% 65 | \noindent{\large\bf\sffamily\strut #1}\par 66 | \nopagebreak\vspace{.8ex plus.8ex minus.3ex}\nopagebreak% 67 | } 68 | 69 | \newcounter{headercount} 70 | \renewcommand{\theheadercount}{\Roman{headercount}} 71 | \newcommand{\header}[1]{% 72 | \refstepcounter{headercount}\headernono{Часть \Roman{headercount}. #1} 73 | } 74 | 75 | \newcounter{lheadercount}[headercount] 76 | \renewcommand{\thelheadercount}{\theheadercount.\arabic{lheadercount}} 77 | \newcommand{\lheader}[1]{% 78 | \par\vspace{0.5ex plus1ex}\pagebreak[2]% 79 | \refstepcounter{lheadercount}{\bf \S\arabic{lheadercount}. #1.}\nopagebreak{}% 80 | } 81 | 82 | \newcommand{\Header}[1]{% 83 | \par\pagebreak[2]\vspace{2.7ex plus 1.3ex minus 1.3ex}% 84 | \noindent{\Large\bf\sffamily #1}\par 85 | \nopagebreak\vspace{2ex plus 1ex minus 1ex}% 86 | } 87 | 88 | \newcounter{llheadercount}[lheadercount] 89 | \renewcommand{\thellheadercount}{\thelheadercount.\arabic{llheadercount}} 90 | \newcommand{\llheader}{% 91 | \par\pagebreak[3]% 92 | \refstepcounter{llheadercount}{\bf \arabic{llheadercount}.} % 93 | } 94 | 95 | %\def\nought{\ensuremath{{\mkern-3.25mu{\not}\mkern3.25mu\mbox{\tt0}}}} 96 | \def\slnought{{\tt\O}} 97 | 98 | \newcommand{\todo}[1]{\marginpar{\raggedright\footnotesize!~TODO:\\#1}} 99 | 100 | \renewcommand{\@oddhead}{} 101 | 102 | \renewcommand{\@oddfoot}{% 103 | \vbox{% 104 | \hrule\vspace{0.1cm}% 105 | \hbox to \textwidth{% 106 | \sf\footnotesize% 107 | \hfill\strut Страница \thepage\ из \pageref{LastPage}\hfill% 108 | }}} 109 | 110 | \renewcommand{\leq}{\leqslant} 111 | \renewcommand{\le}{\leqslant} 112 | \renewcommand{\geq}{\geqslant} 113 | 114 | \newcommand{\unit}[1]{\mbox{ \rm #1}} 115 | % \vstring#1 116 | % Написать #1 как строку вх/вых файла (в кавычках шрифтом \tt без 117 | % переносов) 118 | \newcommand*{\vstring}[1]{`\mbox{\tt#1}'} 119 | 120 | %БАГ: пока не работает генерация автоматических ссылок на пункты перечня 121 | \newcounter{tmp} 122 | 123 | \newenvironment{ulists}[2]{% 124 | \bgroup\begin{list}{#1}{\topsep=0.6ex plus 0.3ex minus 0.6ex \partopsep=0.6ex minus 0.6ex \parsep=0pt \itemsep=0pt #2}% 125 | } 126 | {\end{list}\egroup} 127 | 128 | \newenvironment{ulist}{% 129 | \begin{ulists}{$\bullet$}{}% 130 | } 131 | {\end{ulists}} 132 | 133 | \newenvironment{olist}{% 134 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 135 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{}% 136 | } 137 | {\end{ulists}} 138 | 139 | \newenvironment{olistzero}{% 140 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 141 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \partopsep=0ex}% 142 | } 143 | {\end{ulists}} 144 | 145 | \newenvironment{wideolist}{% 146 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 147 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \parsep=0pt \itemsep=0pt \leftmargin=0pt \itemindent=\labelwidth}% 148 | } 149 | {\end{ulists}} 150 | 151 | % Нумерованный список с сквозной нумерацией 152 | \newcounter{olistcount}\renewcommand{\theolistcount}{\arabic{olistcount}} 153 | \newcommand{\resetolist}{\setcounter{olistcount}{0}} 154 | \newenvironment{olistc}{% 155 | \renewcommand{\theolistcount}{\arabic{olistcount}} 156 | \begin{ulists}{\refstepcounter{olistcount}\theolistcount.}{}% 157 | } 158 | {\end{ulists}} 159 | 160 | % Нумерованный список для использования в тексте, когда каждый пункт 161 | % пишется с маленькой буквы и отделяется ";". 162 | % Здесь помечается арабской цифрой со скобкой. 163 | \newenvironment{tllist}{% 164 | \setcounter{tmp}{0} 165 | \begin{ulists}{\refstepcounter{tmp}\thetmp)}{}% 166 | } 167 | {\end{ulists}} 168 | 169 | \newcommand*{\hm}[1]{#1\nobreak\discretionary{}{\hbox{$\mathsurround=0pt #1$}}{}} 170 | 171 | \newcommand{\wvec}[1]{\overrightarrow{#1}} 172 | 173 | \newcommand{\wnote}[1]{{\sl [~#1~]\todo{!}}} 174 | 175 | \relpenalty=10000 176 | \binoppenalty=10000 177 | 178 | \newcommand{\OR}{\mathrel{\mathrm{or}}} 179 | \newcommand{\XOR}{\mathrel{\mathrm{xor}}} 180 | \newcommand{\AND}{\mathrel{\mathrm{and}}} 181 | \newcommand{\NOT}{\mathop{\mathrm{not}}} 182 | \newcommand{\SHL}{\mathop{\mathrm{shl}}} 183 | \newcommand{\SHR}{\mathop{\mathrm{shr}}} 184 | 185 | 186 | % Суммарная ширина столбцов в двухколоночной таблице, выровненной по ширине 187 | \newlength\twowidth 188 | \newcommand{\settwowidth}{ 189 | \twowidth=\textwidth 190 | \addtolength\twowidth{-4\tabcolsep} 191 | \addtolength\twowidth{-3\arrayrulewidth} 192 | } 193 | \AtBeginDocument{\settwowidth}%т.к. \textwidth надо сначала установить 194 | 195 | % --= поддержка примеров программ, сделаных conv.pas =-- 196 | % Это для борьбы с разрывами страницы после окружений multicols 197 | \newlength{\cs@topskip} 198 | \newlength{\cs@bottom} 199 | \newlength{\cs@bottomback} 200 | \newlength{\cs@top} 201 | \cs@topskip=1.5ex 202 | \cs@bottom=1.5ex 203 | \cs@bottomback=1ex plus 0.5ex minus 0.3ex 204 | \footnotesize\cs@top=2.4ex\normalsize 205 | 206 | \newenvironment{codesamplec}[1] 207 | {% локальные определения: 208 | \newcommand{\codelf}{\kern-1.5em\\}% 209 | \newcommand{\codespace}{{\ttfamily\symbol{`\ }}}% 210 | \newcommand{\codetok}[1]{{\bfseries##1}}% 211 | \newcommand{\codecmt}[1]{{\ttfamily\slshape##1}}% 212 | \vspace{0.5ex plus 0.3ex minus 0.1ex} 213 | \topskip=\cs@topskip%KAP: не знаю почему, но работает :):):) !!! От этого параметра зависимость --- пороговая. Пришлось еще подрегулировать \vspace строкой ниже 214 | %KAP: тут где-то еще видимо затесался vspace с plus/minus компонентой, так что, если сильно ужимать страницу, то все переедет... 215 | \par\begin{multicols}{#1}[\footnotesize\hrule\nopagebreak\vspace{-\cs@top}]\tt\noindent} 216 | {\end{multicols}\par\vspace*{-\cs@bottom}\hrule\vspace*{\cs@bottomback}\pagebreak[0]} 217 | 218 | \newenvironment{codesample}{\begin{codesamplec}{2}}{\end{codesamplec}} 219 | 220 | \newenvironment{codesampleo} 221 | {\vspace{0.5ex plus 0.3ex minus 0.1ex} 222 | \par\footnotesize\hrule\nopagebreak\vspace{-1.3ex}\tt\noindent} 223 | {\par\nopagebreak\vspace{-1.3ex}\hrule\vspace{\cs@bottomback}} 224 | 225 | % --= * =-- 226 | 227 | \newcommand{\noten}[2]{{\vspace{0.1cm}\par\pagebreak[3]\small \textit{#1:} #2 \vspace{0.1cm plus 0.1cm}\par}} 228 | \newcommand{\note}[1]{\noten{Примечание}{#1}} 229 | 230 | \newcommand{\eps}{\varepsilon} 231 | 232 | \newcommand{\epigraph}[2]{%\hangindent=0.4\textwidth\begin{flushright}\small\textit{#1}\par\footnotesize#2\par\end{flushright} 233 | {\parindent=0cm 234 | \parshape 1 0.4\textwidth 0.6\textwidth 235 | \begin{flushright}% 236 | \small\textit{#1}\par% 237 | \vspace{0.1cm}% 238 | \footnotesize#2\par% 239 | \end{flushright}}% 240 | } 241 | 242 | \newcounter{taskcount} 243 | \renewcommand{\thetaskcount}{\arabic{taskcount}} 244 | \newcommand{\taskon}[2]{% 245 | \refstepcounter{taskcount}% 246 | \textbf{#1\mbox{~}\thetaskcount:} {\it #2}% 247 | } 248 | \newcommand{\tasko}[1]{\taskon{Задание}{#1}} 249 | 250 | \newcommand{\hint}[2]{\textbf{Посказка \ref{#1}:} #2} 251 | 252 | \newcommand{\answer}[2]{\textbf{Ответ \ref{#1}:} #2} 253 | 254 | \renewcommand{\ddots}{\,\,.\,.\,\,} 255 | 256 | %ANSWERS + 257 | \newlinechar=`\^^M 258 | 259 | \newwrite\tsk 260 | \immediate\openout\tsk=\jobname.tsk\relax 261 | \newwrite\ans 262 | \immediate\openout\ans=\jobname.ans\relax 263 | \newwrite\hnt 264 | \immediate\openout\hnt=\jobname.hnt\relax 265 | \newwrite\dup 266 | 267 | \def\makerusother{% 268 | \@tempcnta128\relax% 269 | \loop% 270 | \catcode\@tempcnta12% 271 | \ifnum\@tempcnta<255\relax% 272 | \advance\@tempcnta\@ne% 273 | \repeat% 274 | } 275 | 276 | \def\makeallother{% 277 | \let\do\@makeother\dospecials% 278 | \makerusother% 279 | } 280 | 281 | \def\writeansno#1#2{% 282 | \begingroup% 283 | \makeallother% 284 | \obeylines% 285 | \long\def\copyans#2##1#2{% 286 | \def\tmp{##1}% 287 | \if\tmp\empty% 288 | \else% 289 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 290 | \immediate\write#1{##1}% 291 | \fi% 292 | \endgroup\afterwriteans% 293 | }% 294 | \copyans#2% 295 | } 296 | 297 | \def\dupeans#1#2{% 298 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 299 | \immediate\openout\dup=\jobname.dup\relax% 300 | \begingroup% 301 | \makeallother% 302 | \obeylines% 303 | \long\def\copyans#2##1#2{% 304 | \immediate\write#1{##1}% 305 | \immediate\write\dup{##1\noexpand\endinput}% 306 | \endgroup\immediate\closeout\dup% 307 | \input{\jobname.dup}% 308 | \afterwriteans% 309 | }% 310 | \copyans#2% 311 | } 312 | 313 | \def\tasknn#1{% 314 | \endgroup% 315 | \refstepcounter{taskcount}% 316 | \gdef\taskname{#1}% 317 | \immediate\openout\dup=\jobname.dup\relax% 318 | \immediate\write\dup{\noexpand\taskcaption{\taskname{}\noexpand~\thetaskcount:}\noexpand\endinput}% 319 | \immediate\closeout\dup% 320 | \input{\jobname.dup}% 321 | \let\afterwriteans\relax% 322 | \gdef\afterwriteans{% 323 | \gdef\afterwriteans{% 324 | \let\afterwriteans\endgroup% 325 | \writeansno\ans% 326 | }% 327 | \writeansno\hnt% 328 | } 329 | \begingroup\it% 330 | \dupeans\tsk% 331 | } 332 | 333 | \def\taskn{% 334 | \begingroup\makerusother\tasknn% 335 | } 336 | 337 | {\makerusother 338 | \gdef\deftaskname{Задание} 339 | } 340 | 341 | \def\task{\taskn{\deftaskname}} 342 | 343 | \def\taskcaption#1{\textbf{#1}} 344 | 345 | \long\def\answer#1#2{ 346 | \par\pagebreak[3]\mbox{\taskcaption{#1} (стр. #2):} 347 | } 348 | 349 | \def\inputanswers{% 350 | \immediate\closeout\tsk 351 | \immediate\closeout\hnt 352 | \immediate\closeout\ans 353 | \eject\header{Условия всех задач} 354 | \input{\jobname.tsk} 355 | \eject\header{Подсказки} 356 | \input{\jobname.hnt} 357 | \eject\header{Ответы} 358 | \input{\jobname.ans} 359 | } 360 | 361 | -------------------------------------------------------------------------------- /04_dfs/04_dfs.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \documentclass[a4paper,10pt]{problems} 5 | 6 | \begin{document} 7 | 8 | \input{04_dfs_main.tex} 9 | 10 | \end{document} 11 | -------------------------------------------------------------------------------- /04_dfs/04_dfs_main.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \Header{Поиск в глубину} 5 | 6 | Поиск в глубину "--- удивительный алгоритм. С одной стороны, он очень прост для реализации и 7 | довольно прост для понимания, а с другой стороны, имеет столько применений для различных 8 | стандартных задач, сколько, пожалуй, не имеет ни один другой алгоритм. Если большинство других 9 | алгоритмов решают вполне конкретную задачу, то поиск в глубину сам по себе "--- скорее шаблон для 10 | написания алгоритмов решения для целого набора задач. Я тут постараюсь рассказать применения его 11 | для почти всех задач, которые знаю; некоторые из этих применения попроще, некоторые посложнее, 12 | надеюсь, что хотя бы часть будет понятна. 13 | 14 | %\input{texts/04_0_intro.tex} 15 | \input{texts/04_1_dfs.tex} 16 | \input{texts/04_2_simple.tex} 17 | \input{texts/04_3_topsort.tex} 18 | \input{texts/04_4_bridges.tex} 19 | \input{texts/04_5_problems.tex} 20 | %\input{texts/04_6_hints.tex} 21 | %\input{texts/04_7_answers.tex} 22 | -------------------------------------------------------------------------------- /04_dfs/do.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd texts/04_1_dfs 3 | mpost graph.mp 4 | cd ../04_2_simple 5 | mpost graph.mp 6 | cd ../04_3_topsort 7 | mpost graph.mp 8 | cd ../04_4_bridges 9 | mpost conj.mp 10 | cd ../.. 11 | latex 04_dfs.tex 12 | dvipdfmx -p a4 04_dfs.dvi -------------------------------------------------------------------------------- /04_dfs/graphics.cfg: -------------------------------------------------------------------------------- 1 | \ProvidesFile{graphics.cfg}% stolen from TL/teTeX 2 | [2003/03/12 v1.1 MiKTeX 'graphics' configuration] 3 | 4 | % Select an appropriate default driver 5 | \begingroup 6 | \chardef\x=0 % 7 | % check pdfTeX 8 | \@ifundefined{pdfoutput}{}{% 9 | \ifcase\pdfoutput 10 | \else 11 | \chardef\x=1 % 12 | \fi 13 | }% 14 | \expandafter\endgroup 15 | \ifcase\x 16 | % default case 17 | \ExecuteOptions{dvips}% 18 | \else 19 | % pdfTeX is running in pdf mode 20 | \ExecuteOptions{pdftex}% 21 | \fi 22 | 23 | % Fix for dvips and xdvi versions that can uncompress 24 | % graphic files without an explicite call of gunzip. 25 | % (The fix is not applied for miniltx.tex, because 26 | % \AtEndOfPackage is not available in plainTeX.) 27 | \endinput 28 | -------------------------------------------------------------------------------- /04_dfs/problems.cls: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e} 2 | \ProvidesClass{problems}[2006/11/03] 3 | 4 | % identification 5 | % initial code 6 | % declaration of options 7 | % execution of options 8 | % package loading 9 | % main code 10 | 11 | % Declaration of Options 12 | \DeclareOption{draft}{\PassOptionsToClass{draft}{article}\AtEndOfClass{\geometry{showframe}}} 13 | \DeclareOption{10pt}{\PassOptionsToClass{10pt}{article}} 14 | \DeclareOption{11pt}{\PassOptionsToClass{11pt}{article}} 15 | \DeclareOption{12pt}{\PassOptionsToClass{12pt}{article}} 16 | 17 | 18 | % Опцию a4paper будем использовать для формата, в котором задачки 19 | % печатались раньше на бумаге A4. 20 | \DeclareOption{a4paper}{ 21 | \PassOptionsToPackage{a4paper,includehead,includefoot,headheight=10pt,headsep=2mm,width=17cm,height=27cm,footskip=0.5cm}{geometry} 22 | } 23 | 24 | % Execution of Options 25 | \ProcessOptions\relax 26 | 27 | % Package Loading 28 | \LoadClass[a4paper]{article} 29 | 30 | \RequirePackage[T2A]{fontenc} 31 | \RequirePackage[utf8]{inputenc} 32 | \RequirePackage{mathtext} 33 | \RequirePackage[english,russian]{babel} 34 | \RequirePackage[dvips,final]{graphicx} 35 | \RequirePackage{wrapfig} 36 | \RequirePackage{amssymb} 37 | \RequirePackage{amsmath} 38 | \RequirePackage{amscd} 39 | \RequirePackage{array} 40 | \RequirePackage{multicol} 41 | \RequirePackage{longtable} 42 | %\RequirePackage{fancyvrb} 43 | \RequirePackage[dvips]{geometry} 44 | 45 | % Main Code 46 | \columnseprule=0.4pt 47 | \raggedbottom 48 | 49 | % AK: думаю, лучше везде использовать вариант "". 50 | %\declare@shorthand{russian}{""}{\nobreak\hskip.2em\ignorespaces} 51 | %\declare@shorthand{russian}{",}{\nobreak\hskip.2em\ignorespaces} 52 | % KAP: чтобы кавычки всегда были правильные 53 | %\declare@shorthand{russian}{"<}{<<} 54 | %\declare@shorthand{russian}{">}{>>} 55 | %---------- From package "lastpage" ------------------ 56 | \def\lastpage@putlabel{\addtocounter{page}{-1}% 57 | \immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}% 58 | \addtocounter{page}{1}} 59 | \AtEndDocument{\clearpage\lastpage@putlabel}% 60 | %---------- end of "lastpage" ------------------ 61 | 62 | \newcommand{\headernono}[1]{% 63 | \par\pagebreak[2]\vspace{1.5ex plus1ex minus .7ex}% 64 | \noindent{\large\bf\sffamily\strut #1}\par 65 | \nopagebreak\vspace{.8ex plus.8ex minus.3ex}% 66 | } 67 | 68 | \newcounter{headercount} 69 | \renewcommand{\theheadercount}{\Roman{headercount}} 70 | \newcommand{\header}[1]{% 71 | \refstepcounter{headercount}\headernono{Часть \Roman{headercount}. #1} 72 | } 73 | 74 | \newcounter{lheadercount}[headercount] 75 | \renewcommand{\thelheadercount}{\theheadercount.\arabic{lheadercount}} 76 | \newcommand{\lheader}[1]{% 77 | \par\pagebreak[3]\vspace{0.5ex plus1ex}% 78 | \refstepcounter{lheadercount}{\bf \S\arabic{lheadercount}. #1.}% 79 | } 80 | 81 | \newcommand{\Header}[1]{% 82 | \par\pagebreak[2]\vspace{2.7ex plus 1.3ex minus 1.3ex}% 83 | \noindent{\Large\bf\sffamily #1}\par 84 | \nopagebreak\vspace{2ex plus 1ex minus 1ex}% 85 | } 86 | 87 | %\def\nought{\ensuremath{{\mkern-3.25mu{\not}\mkern3.25mu\mbox{\tt0}}}} 88 | \def\slnought{{\tt\O}} 89 | 90 | %\DefineVerbatimEnvironment{codeblock}{Verbatim}{xleftmargin=\parindent} 91 | 92 | \newcommand{\todo}[1]{\marginpar{\raggedright\footnotesize!~TODO:\\#1}} 93 | 94 | \renewcommand{\@oddhead}{} 95 | 96 | \renewcommand{\@oddfoot}{% 97 | \vbox{% 98 | \hrule\vspace{0.1cm}% 99 | \hbox to \textwidth{% 100 | \sf\footnotesize% 101 | \hfill\strut Страница \thepage\ из \pageref{LastPage}\hfill% 102 | }}} 103 | 104 | \renewcommand{\leq}{\leqslant} 105 | \renewcommand{\le}{\leqslant} 106 | \renewcommand{\geq}{\geqslant} 107 | 108 | \newcommand{\unit}[1]{\mbox{ \rm #1}} 109 | % \vstring#1 110 | % Написать #1 как строку вх/вых файла (в кавычках шрифтом \tt без 111 | % переносов) 112 | \newcommand*{\vstring}[1]{`\mbox{\tt#1}'} 113 | 114 | %БАГ: пока не работает генерация автоматических ссылок на пункты перечня 115 | \newcounter{tmp} 116 | 117 | \newenvironment{ulists}[2]{% 118 | \begin{list}{#1}{\topsep=0.6ex plus 0.3ex minus 0.6ex \partopsep=0.6ex minus 0.6ex \parsep=0pt \itemsep=0pt #2}% 119 | } 120 | {\end{list}} 121 | 122 | \newenvironment{ulist}{% 123 | \begin{ulists}{$\bullet$}{}% 124 | } 125 | {\end{ulists}} 126 | 127 | \newenvironment{olist}{% 128 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 129 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{}% 130 | } 131 | {\end{ulists}} 132 | 133 | \newenvironment{olistzero}{% 134 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 135 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \partopsep=0ex}% 136 | } 137 | {\end{ulists}} 138 | 139 | \newenvironment{wideolist}{% 140 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 141 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \parsep=0pt \itemsep=0pt \leftmargin=0pt \itemindent=\labelwidth}% 142 | } 143 | {\end{ulists}} 144 | 145 | % Нумерованный список с сквозной нумерацией 146 | \newcounter{olistcount}\renewcommand{\theolistcount}{\arabic{olistcount}} 147 | \newcommand{\resetolist}{\setcounter{olistcount}{0}} 148 | \newenvironment{olistc}{% 149 | \renewcommand{\theolistcount}{\arabic{olistcount}} 150 | \begin{ulists}{\refstepcounter{olistcount}\theolistcount.}{}% 151 | } 152 | {\end{ulists}} 153 | 154 | % Нумерованный список для использования в тексте, когда каждый пункт 155 | % пишется с маленькой буквы и отделяется ";". 156 | % Здесь помечается арабской цифрой со скобкой. 157 | \newenvironment{tllist}{% 158 | \setcounter{tmp}{0} 159 | \begin{ulists}{\refstepcounter{tmp}\thetmp)}{}% 160 | } 161 | {\end{ulists}} 162 | 163 | \newcommand*{\hm}[1]{#1\nobreak\discretionary{}{\hbox{$\mathsurround=0pt #1$}}{}} 164 | 165 | \newcommand{\wvec}[1]{\overrightarrow{#1}} 166 | 167 | \newcommand{\wnote}[1]{{\sl [~#1~]\todo{!}}} 168 | 169 | \relpenalty=10000 170 | \binoppenalty=10000 171 | 172 | 173 | % Суммарная ширина столбцов в двухколоночной таблице, выровненной по ширине 174 | \newlength\twowidth 175 | \newcommand{\settwowidth}{ 176 | \twowidth=\textwidth 177 | \addtolength\twowidth{-4\tabcolsep} 178 | \addtolength\twowidth{-3\arrayrulewidth} 179 | } 180 | \AtBeginDocument{\settwowidth}%т.к. \textwidth надо сначала установить 181 | 182 | % --= поддержка примеров программ, сделаных conv.pas =-- 183 | % Это для борьбы с разрывами страницы после окружений multicols 184 | \newlength{\cs@topskip} 185 | \newlength{\cs@bottom} 186 | \newlength{\cs@bottomback} 187 | \newlength{\cs@top} 188 | \cs@topskip=1.5ex 189 | \cs@bottom=1.5ex 190 | \cs@bottomback=1ex plus 0.5ex minus 0.3ex 191 | \footnotesize\cs@top=2.4ex\normalsize 192 | 193 | \newenvironment{codesamplec}[1] 194 | {% локальные определения: 195 | \newcommand{\codelf}{\kern-1.5em\\}% 196 | \newcommand{\codespace}{{\ttfamily\symbol{`\ }}}% 197 | \newcommand{\codetok}[1]{{\bfseries##1}}% 198 | \newcommand{\codecmt}[1]{{\ttfamily\slshape##1}}% 199 | \vspace{0.5ex plus 0.3ex minus 0.1ex} 200 | \topskip=\cs@topskip%KAP: не знаю почему, но работает :):):) !!! От этого параметра зависимость --- пороговая. Пришлось еще подрегулировать \vspace строкой ниже 201 | %KAP: тут где-то еще видимо затесался vspace с plus/minus компонентой, так что, если сильно ужимать страницу, то все переедет... 202 | \par\begin{multicols}{#1}[\footnotesize\hrule\nopagebreak\vspace{-\cs@top}]\tt\noindent} 203 | {\end{multicols}\par\vspace*{-\cs@bottom}\hrule\vspace*{\cs@bottomback}\pagebreak[0]} 204 | 205 | \newenvironment{codesample}{\begin{codesamplec}{2}}{\end{codesamplec}} 206 | 207 | \newenvironment{codesampleo} 208 | {\vspace{0.5ex plus 0.3ex minus 0.1ex} 209 | \par\footnotesize\hrule\nopagebreak\vspace{-1.3ex}\tt\noindent} 210 | {\par\nopagebreak\vspace{-1.3ex}\hrule\vspace{\cs@bottomback}} 211 | 212 | % --= * =-- 213 | 214 | \newcommand{\note}[1]{{\par\pagebreak[3]\small \textit{Примечание:} #1 \par}} 215 | 216 | \newcommand{\eps}{\varepsilon} 217 | 218 | \newcommand{\epigraph}[2]{\hangindent=0.4\textwidth\begin{flushright}\small\textit{#1}\par\footnotesize#2\par\end{flushright}} 219 | 220 | 221 | \newcounter{taskcount} 222 | \renewcommand{\thetaskcount}{\arabic{taskcount}} 223 | \newcommand{\taskn}[2]{\refstepcounter{taskcount}\textbf{#1 \thetaskcount:} {\it #2}} 224 | \newcommand{\task}[1]{\taskn{Задание}{#1}} 225 | 226 | \newcommand{\hint}[2]{\textbf{Посказка \ref{#1}:} #2} 227 | 228 | \newcommand{\answer}[2]{\textbf{Ответ \ref{#1}:} #2} -------------------------------------------------------------------------------- /04_dfs/texts/04_0_intro.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \headernono{Вместо вступления :)} 5 | В этой теме опять будет большое количество задач. Поэтому я тут напишу моё мнение по поводу того, что с ними делать. 6 | Во"=первых, почти по по каждой задаче есть ответ, а по некоторым задачам "--- ещё и подсказки. Они попали в конец 7 | на отдельные страницы. Я надеюсь, что по каждой задаче в итоге вы прочитаете и подсказку (ели она есть), и ответ. 8 | По некоторым задачам ответа нет "--- думайте над ними сами. 9 | 10 | Но, конечно, стоит над задачами сначала думать, а только потом читать подсказки/ответы. Я надеюсь, 11 | что у вас будет достаточно времени на размышления. Не ленитесь писать задачи :) на самом деле тут все просто, 12 | и человек, который все это хорошо знает, потратит на написание и тестирование каждой задачи максимум минут 13 | пятнадцать-двадцать, поэтому три десятка задач "--- это работа всего на один день :). У вас с первого раза это, 14 | скорее всего, займёт больше времени, но это только лишний повод не полениться 15 | и сделать все задачи. 16 | 17 | ИМХО, можно придерживаться следующего "<алгоритма"> работы над задачами: 18 | \begin{olist} 19 | \item[0.] Дочитать соответствующую теорию. Осознать, что вы все тут понимаете и что, скорее всего, вопросов по 20 | написанию программы у вас не возникнет. Если возникают какие"=то вопросы, то ещё раз прочитать текст :), 21 | но не забывать и самим додумывать то, что вы прочитали. Я хоть и старался расписывать все подробно, 22 | но, конечно, собственное размышление также должно присутствовать. Кроме того, учтите, что у меня вполне могут быть 23 | различные опечатки и даже ошибки как в тексте, так и в примерах кода. 24 | \item Начать писать программу. Довести её до состояния, что она компилируется и запускается. Если не получается 25 | и не знаете, что писать, то см. п. 0. 26 | \item Начать тестировать задачу. Сначала на маленьких простых тестах, потом на более крутых. Постарайтесь проверить 27 | все возможные подлые случаи. Пользуйтесь тем, что вы знаете правильный алгоритм и потому можете продумать, какие случаи 28 | для него будут наиболее подлыми (но, конечно, тестируйте и другие случаи). 29 | 30 | Если нашли тест, на котором программа работает неправильно, то 31 | \begin{ulist} 32 | \item Попробуйте попреобразовывать тест, уменьшая его размер, так, чтобы получить как можно более маленький тест, 33 | на котором программа не работает. 34 | \item Попробуйте "<методом пристального всматривания"> в тест понять, в чем состоит его особенность, что на нем программа 35 | не работает, чем таким он отличается от тестов, на которых программа работает (конечно, это для случаев, когда 36 | программа на большинстве тестов все"=таки работает). 37 | \item Здесь все алгоритмы довольно простые. Попробуйте прогнать алгоритм на этом тесте вручную, и проверьте, 38 | что он правильно работает. Если нет, то ищите ошибку или в вашем понимании алгоритма, или в вашем понимании задачи, 39 | которую вы решаете. Не забывайте, что у меня в тексте могут быть ошибки :) 40 | \item Попробуйте подебаггать тем или иным способом вашу программу. Можно добавлять ", чтобы 41 | программа выводила на экран (или в файл), что и в каком порядке она делает, можно дебаггать встроенным дебаггером 42 | паскаля. Не забывайте, что BP своеобразно работает при дебаге рекурсивных программ. При дебагге проверяйте, что 43 | все ключевые переменные принимают именно те значения, которые вы от них ожидаете. Обнаружив отклонение, 44 | ищите его корень :) 45 | \end{ulist} 46 | \end{olist} 47 | 48 | Постарайтесь продвинуться по этому алгоритму как можно дальше \textit{до} чтения подсказок и ответов. Если вы получили 49 | полностью работающую программу, которая проходит все ваши, даже очень подлые, тесты, вы круты. Обязательно прочитайте 50 | подсказку и ответ. 51 | 52 | Учтите также, что любые задачи 53 | подразумевают, что вы хоть чуть"=чуть, но изобретёте что"=нибудь! Если вы 54 | придумаете свой вариант решения, круто "--- напишите и проверьте его, т.е. действуйте дальше по алгоритму. 55 | 56 | Если за пару дней не получается решить задачу, читайте подсказку, если она есть. Потом опять повторяйте все вышеприведённые 57 | шаги. Только после этого читайте ответ и, если до сих пор у вас нет работающей программы, то напишите её. Обязательно постарайтесь 58 | доведите каждую задачу до работающего состояния. Если даже у вас 59 | была работающая программа, подумайте, нельзя ли её ещё улучшить, пользуясь подсказкой и ответом. 60 | 61 | Это все в первую очередь относится к задачам, которые подразумевают написание программы. Аналогично можно поступать и 62 | с нетривиальными теоретическими задачами; но есть пара задач, которые требуют ответа сразу, не читая текста дальше. 63 | Про них действительно подумайте немного, пока не будете уверены, что можете дать уверенный ответ с обоснованием. Потом 64 | сверьтесь с ответом и читайте дальше. 65 | 66 | Если у вас под рукой нет компьютера, это имхо тоже не повод сразу читать ответы. Можно вообще отложить решение тех задач, 67 | которые требуют компьютера, до тех пор, когда вы получите к нему доступ. Но по крайней мере можно 68 | довести работу над задачей до готового текста программы, написанного на бумажке, чтобы убедиться, что вы можете пройти 69 | первые два из вышеприведённых шагов. На данном этапе имхо написать программу, будучи почти уверенным в ней "--- это половина 70 | всего дела! 71 | 72 | Кроме задач, конечно, я рассчитываю, что вы напишите (т.е. доведёте до работающей оттестированной программы) все 73 | обсуждаемые здесь алгоритмы, конечно, по вышеприведённой схеме. Полезно будет сначала проглядеть его 74 | реализацию, приводимую мною в тексте, убедиться, что вы все понимаете, и после этого писать программу, не подглядывая 75 | в текст. 76 | -------------------------------------------------------------------------------- /04_dfs/texts/04_1_dfs/graph.mp: -------------------------------------------------------------------------------- 1 | prologues:=0; 2 | u:=1cm; 3 | 4 | pair A,B,C,D,E,F; 5 | A:=(0,0); 6 | B:=(-1u,1u); 7 | C:=(-2u,0); 8 | D:=(-1u,-1u); 9 | E:=(1u,1u); 10 | F:=(1u,-1u); 11 | 12 | def drawgr= 13 | draw A--B--C--D--E--F--A--C; 14 | pickup pencircle scaled (u/5); 15 | draw A; 16 | draw B; 17 | draw C; 18 | draw D; 19 | draw E; 20 | draw F; 21 | label.top(btex 1 etex,A); 22 | label.bot(btex 3 etex,B); 23 | label.top(btex 2 etex,C); 24 | label.top(btex 4 etex,D); 25 | label.rt(btex 5 etex,E); 26 | label.rt(btex 6 etex,F); 27 | enddef; 28 | 29 | beginfig(1) 30 | drawgr; 31 | endfig; 32 | 33 | beginfig(2) 34 | drawgr; 35 | pickup pencircle scaled (u/10); 36 | draw A--C--B; 37 | draw C--D; 38 | draw A--E--F; 39 | endfig; 40 | 41 | bye 42 | -------------------------------------------------------------------------------- /04_dfs/texts/04_2_simple/graph.mp: -------------------------------------------------------------------------------- 1 | prologues:=0; 2 | u:=1cm; 3 | 4 | pair A,B,C,D,E,F; 5 | A:=(0,0); 6 | B:=(-1u,1u); 7 | C:=(-2u,0); 8 | D:=(-1u,-1u); 9 | E:=(1u,1u); 10 | F:=(1u,-1u); 11 | 12 | def drawgr= 13 | draw A--B--C--D--E--F--A; 14 | pickup pencircle scaled (u/5); 15 | draw A; 16 | draw B; 17 | draw C; 18 | draw D; 19 | draw E; 20 | draw F; 21 | label.top(btex 2 etex,A); 22 | label.bot(btex 3 etex,B); 23 | label.top(btex 1 etex,C); 24 | label.top(btex 4 etex,D); 25 | label.rt(btex 5 etex,E); 26 | label.rt(btex 6 etex,F); 27 | enddef; 28 | 29 | beginfig(1) 30 | drawgr; 31 | endfig; 32 | 33 | %beginfig(2) 34 | %drawgr; 35 | %pickup pencircle scaled (u/10); 36 | %draw A--C--B; 37 | %draw C--D; 38 | %draw A--E--F; 39 | %endfig; 40 | 41 | bye 42 | -------------------------------------------------------------------------------- /04_dfs/texts/04_3_topsort/graph.mp: -------------------------------------------------------------------------------- 1 | prologues:=0; 2 | u:=1.5cm; 3 | ahlength:=u/4.5; 4 | ahangle:=30; 5 | 6 | pair A,B,C,D,E,F,DEu,DEd; 7 | A:=(0,0); 8 | B:=(0u,1u); 9 | C:=(1u,0); 10 | D:=(1u,1u); 11 | E:=(2u,1u); 12 | F:=(2u,0); 13 | DEu:=0.5[D,E]+(0,0.2u); 14 | DEd:=0.5[D,E]-(0,0.2u); 15 | 16 | def drawgr= 17 | drawarrow A--B; 18 | drawarrow B--C; 19 | drawarrow C--A; 20 | drawarrow B--D; 21 | drawarrow D..DEu..E; 22 | drawarrow E..DEd..D; 23 | drawarrow E--F; 24 | drawarrow C--F; 25 | drawarrow C--D; 26 | pickup pencircle scaled (u/10); 27 | draw A; 28 | draw B; 29 | draw C; 30 | draw D; 31 | draw E; 32 | draw F; 33 | label.bot(btex 1 etex,A); 34 | label.top(btex 2 etex,B); 35 | label.bot(btex 3 etex,C); 36 | label.top(btex 4 etex,D); 37 | label.rt(btex 5 etex,E); 38 | label.rt(btex 6 etex,F); 39 | enddef; 40 | 41 | beginfig(1) 42 | drawgr; 43 | endfig; 44 | 45 | beginfig(2) 46 | linejoin:=rounded; 47 | filldraw A--B--C--cycle withpen pencircle scaled (u/3) withcolor (0.8,0.8,0.8); 48 | filldraw D..DEu..E--E..DEd..D--cycle withpen pencircle scaled (u/3) withcolor (0.8,0.8,0.8); 49 | draw F withpen pencircle scaled (u/3) withcolor (0.8,0.8,0.8); 50 | drawgr; 51 | endfig; 52 | 53 | beginfig(3) 54 | pair AA,BB,CC,AC; 55 | AA:=(0,0); 56 | BB:=(1u,0); 57 | CC:=(2u,0); 58 | AC:=0.5[AA,CC]+(0,0.4u); 59 | drawarrow AA--BB; 60 | drawarrow BB--CC; 61 | drawarrow AA..AC..CC; 62 | pickup pencircle scaled (u/10); 63 | draw AA; 64 | draw BB; 65 | draw CC; 66 | label.bot(btex $\{1,2,3\}$ etex,AA); 67 | label.bot(btex $\{4,5\}$ etex,BB); 68 | label.bot(btex $\{6\}$ etex,CC); 69 | endfig; 70 | 71 | bye 72 | -------------------------------------------------------------------------------- /04_dfs/texts/04_4_bridges/conj.mp: -------------------------------------------------------------------------------- 1 | u:=1cm; 2 | 3 | vardef drawsub(expr A)= 4 | pair BB,CC; 5 | BB:=A+(0.4u,-1u); 6 | CC:=A+(-0.4u,-1u); 7 | filldraw A--BB--CC--cycle withpen pencircle scaled(u/4) withcolor (0.8,0.8,0.8); 8 | %draw A--0.8[A,BB] dashed evenly; 9 | %draw A--0.8[A,CC] dashed evenly; 10 | enddef; 11 | 12 | beginfig(1) 13 | pair A,B,C,D; 14 | A:=(-0.5u,1u); 15 | B:=(0,0); 16 | C:=(-1u,-1u); 17 | D:=(1u,-1u); 18 | drawsub(C); 19 | drawsub(D); 20 | draw A--B; 21 | draw B--C; 22 | draw B--D; 23 | draw C+(-0.2u,-0.8u)..0.5[B,C]+(-0.8u,0)..A+(-0.2u,0) dashed evenly; 24 | label.lft(btex 1 etex, 0.5[B,C]+(-0.8u,0)); 25 | draw D+(0,-0.8u)--C+(0,-0.3u) dashed evenly; 26 | label.bot(btex 2 etex, 0.5[D+(0,-0.8u),C+(0,-0.3u)]); 27 | pickup pencircle scaled (u/7); 28 | draw B; 29 | draw C; 30 | draw D; 31 | label.rt(btex $u$ etex,B); 32 | label.rt(btex $v_1$ etex, C); 33 | label.rt(btex $v_2$ etex, D); 34 | endfig; 35 | 36 | bye -------------------------------------------------------------------------------- /04_dfs/texts/04_5_problems.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \header{Задачи на поиск в глубину} 5 | 6 | Конечно, я предполагаю, что вы напишите все обсуждавшиеся алгоритмы, решите все вышеприведённые задачи 7 | и напишите и программы по этим задачам. 8 | 9 | \task|Дан граф. Вывести несколько путей так, чтобы по каждому ребру проходил ровно один путь и при этом число путей было 10 | минимальным. В каждом пути вершины могут повторяться, но ребра нет. (В частности, если в графе существует 11 | эйлеров цикл или путь, то надо просто его вывести). 12 | ||Ясно, что число путей будет как минимум равно половине от числа вершин с нечётной степенью; пусть 13 | это число равно $K$, оно всегда чётно. Добавим в наш граф $K/2$ рёбер, попарно (произвольным образом) 14 | соединив наши нечётные вершины. Что дальше? 15 | ||Если добавить $K/2$ рёбер, как это сказано в подсказке, то степени всех вершин станут чётными. 16 | Поэтому найдём в графе эйлеров цикл и потом из него выкинем те ребра, которые мы раньше добавили. Цикл распадётся 17 | на $K/2$ путей, которые и будут ответом на нашу задачу, т.к. меньше путей получить нельзя. 18 | 19 | Бонусное задание: а почему именно на $K/2$? Вдруг у нас несколько удаляемых рёбер в цикле будут идти подряд? 20 | |\label{pathcover} 21 | 22 | \task|Дан граф, в котором точно существует эйлеров цикл (т.е. степени всех вершин чётны). Для каждого ребра $i$ 23 | дано число $x_i$. Для каждого эйлерова цикла в этом графе введём его "<штраф"> следующим образом. 24 | Штраф за одно ребро $i$ будет равен $k-x_i$, где $k$ "--- порядковый номер этого ребра в цикле. Штраф цикла 25 | равен сумме штрафов за все ребра. Требуется найти эйлеров цикл с минимальным штрафом. 26 | ||На самом деле это почти что задача"=шутка. 27 | ||Задача"=шутка. Несложно доказать, что веса всех эйлеровых циклов одинаковы и равны $n(n+1)/2-S$, 28 | где $S$ "--- сумма всех $x_i$, поэтому выводим любой цикл. 29 | |\label{postman} 30 | 31 | \task|Дан неориентированный граф. Ориентировать его (т.е. каждое ребро ориентировать в одно из двух возможных 32 | направлений) так, чтобы он стал ациклическим. Если решения не существует, то сообщить это. 33 | || 34 | ||Очень просто на самом деле, и даже поиск в глубину тут ни при чем. Просто 35 | ориентируем все ребра от вершины с меньшим номером к вершине с б\'{о}льшим. 36 | 37 | Вообще, любой ациклический граф, как мы знаем, можно оттопсортить, и наоборот, любой граф, который можно 38 | оттопсортить (т.е. для которого задача топологической сортировки имеет решение), является ациклическим. 39 | Поэтому можно просто задать произвольный порядок вершин и ориентировать ребра в соответствии с этим порядком, 40 | и, более того, таким образом можно получить \textit{любой} ациклический граф, который вообще можно 41 | получить из данного неориентированного. 42 | |\label{nondirecttoacyclic} 43 | 44 | \task|Дан неориентированный граф. Ориентировать его так, чтобы он стал сильносвязным. 45 | Если решения не существует, то сообщить это. 46 | || 47 | ||Решения не будет существовать тогда и только тогда, когда в графе есть мосты. 48 | Если их нет, то ориентировать надо также, как при поиске мостов, т.е. ребра дерева поиска "--- от корня, 49 | остальные ребра "--- к корню. (На самом деле даже искать мосты не обязательно). 50 | |\label{nondirecttoSC} 51 | 52 | \task|Дан частично ориентированный граф (т.е. некоторые ребра изначально ориентированные, 53 | некоторые нет). Ориентировать неориентированные ребра так, чтобы он стал ациклическим. Если решения не существует, 54 | то сообщить это. 55 | || 56 | ||Выкинем все неориентированные ребра и оттопсортим полученный граф. Если это невозможно, 57 | то задача решения не имеет (почему?). Потом вернём все неориентированные ребра и ориентируем их в соответствии 58 | с полученным в топсорте порядком. 59 | 60 | Бонусное задание: сравните эту задачу с задачей \ref{nondirecttoacyclic}. 61 | |\label{semidirecttoacyclic} 62 | 63 | \task|(Задача 172 с acm.sgu.ru) В некоторой школе проводятся "<экзамены по выбору">. 64 | Каждый ученик должен выбрать два экзамена из данного списка и сдать их. Известно, какой ученик какие экзамены выбрал. 65 | Школа хочет выделить ровно два дня под эти экзамены, при этом в первый день провести часть 66 | экзаменов, а остальные экзамены "--- и только их "--- во второй. Конечно, при этом должно получиться так, 67 | чтобы каждый школьник мог сдать выбранные им экзамены в разные дни. Требуется составить такое 68 | расписание экзаменов (т.е. распределить экзамены по дням) или сообщить, что это невозможно. 69 | || 70 | ||Постройте граф: вершины "--- экзамены, ребра "--- ученики. Осталось проверить его на 71 | двудольность. 72 | |\label{eXam} -------------------------------------------------------------------------------- /04_dfs/texts/04_6_hints.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \cleardoublepage 5 | \header{Подсказки по заданиям} 6 | Естественно, сначала порешайте задачи сами, а потом только читайте подсказки :) Подсказки даю не по всем заданиям. 7 | 8 | \hint{checkiftree}{} 9 | 10 | \hint{Eulercriteria}{} 11 | 12 | \hint{Knuthalgorithm}{} 13 | 14 | \hint{Knuthforacycliccheck}{} 15 | 16 | \hint{transitive}{} 17 | 18 | \hint{howtosort}{} 19 | 20 | \hint{crossedges}{} 21 | 22 | \hint{pathcover}{} 23 | 24 | \hint{postman}{} -------------------------------------------------------------------------------- /04_dfs/texts/04_7_answers.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \cleardoublepage 5 | \header{Ответы} 6 | 7 | 8 | \answer{fillwas}{} 9 | 10 | \answer{ambigousbi}{} 11 | 12 | \answer{whichtask}{} 13 | 14 | \answer{BFS:bipartie}{ 15 | 16 | \answer{tripartie}{} 17 | 18 | \answer{checkiftree}{ 19 | 20 | \answer{Eulercriteria}{} 21 | 22 | \answer{directEuler}{} 23 | 24 | \answer{directEulerpath}{} 25 | 26 | \answer{acyclicnontree}{} 27 | 28 | \answer{Knuthalgorithm}{ 29 | 30 | \answer{connecteddirect}{} 31 | 32 | \answer{acyclicrepeat}{} 33 | 34 | \answer{Knuthforacycliccheck}{} 35 | 36 | \answer{transitive}{} 37 | 38 | \answer{badSCC}{} 39 | 40 | \answer{condensationisacyclic}{} 41 | 42 | \answer{howtosort}{} 43 | 44 | \answer{bridgeone}{} 45 | 46 | \answer{bridgesandSV}{} 47 | 48 | \answer{crossedges}{} 49 | 50 | \answer{dots}{} 51 | 52 | \answer{bridgesstupid}{} 53 | 54 | \answer{bridgesadv}{} 55 | 56 | \answer{pathcover}{} 57 | 58 | \answer{postman}{} 59 | 60 | \answer{nondirecttoacyclic}{} 61 | 62 | \answer{nondirecttoSC}{} 63 | 64 | \answer{semidirecttoacyclic}{} 65 | 66 | \answer{eXam}{} -------------------------------------------------------------------------------- /05_dynprog/05_dynprog.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \documentclass[a4paper,10pt]{problems} 5 | 6 | \begin{document} 7 | 8 | {\makerusother\relax 9 | \immediate\write\tsk{\noexpand\epigraph{\noexpand\dotsупражнений, которые настоятельно и, как всегда, 10 | безуспешно, рекомендую делать\noexpand\dots}{}} 11 | } 12 | 13 | 14 | \input{05_dynprog_main.tex} 15 | 16 | \epigraph{Вы не ужасайтесь\dots{} реально все тривиально\dots}{} 17 | 18 | \inputanswers 19 | 20 | \end{document} 21 | -------------------------------------------------------------------------------- /05_dynprog/05_dynprog_main.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | 5 | 6 | \epigraph{ 7 | Динамическое программирование "--- это когда у нас 8 | есть одна большая задача, которую непонятно как решать, 9 | и мы разбиваем ее на меньшие задачи, которые тоже 10 | непонятно как решать.\\ 11 | А.""С. Кумок 12 | } 13 | 14 | Динамическое программирование (ДП, динамика) "--- это \textit{метод} решений задач совершенно разных классов. 15 | Пожалуй, это единственный в своём роде раздел олимпиадного программирования: не алгоритм, не 16 | структура данных, а именно метод, идея решения задач. {\footnotesize К динамической памяти он, 17 | конечно, отношения не имеет.} 18 | 19 | ДП идейно очень напоминает метод математический индукции. Это очень полезно держать в голове при 20 | чтении дальнейшего текста, тогда, может быть, все будет проще. 21 | 22 | Может показаться, что ДП "--- это некий чёткий алгоритм построения решения задачи, т.е. 23 | что достаточно его освоить "--- и все соответствующие задачи будут решаться с ходу, без 24 | затруднений. Конечно, это не так; в любых задачах всегда приходится хоть немного, но думать 25 | головой. Поэтому смотрите на все, что я тут написал, как на то, что поможет вам в этом думании; 26 | в каждой конкретной задаче могут возникнуть дополнительные особенности и т.п. 27 | 28 | \input{texts/05_1_elementary.tex} 29 | \input{texts/05_2_fundamental.tex} 30 | \input{texts/05_3_howtogetanswer.tex} 31 | \input{texts/05_4_classes.tex} 32 | \input{texts/05_5_ways.tex} 33 | \input{texts/05_6_dptypes.tex} 34 | \input{texts/05_7_tasks.tex} 35 | -------------------------------------------------------------------------------- /05_dynprog/do.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd texts/05_2_fundamental 3 | mpost graph.mp 4 | mpost tree.mp 5 | cd ../.. 6 | latex 05_dynprog.tex 7 | dvipdfmx -p a4 05_dynprog.dvi -------------------------------------------------------------------------------- /05_dynprog/graphics.cfg: -------------------------------------------------------------------------------- 1 | \ProvidesFile{graphics.cfg}% stolen from TL/teTeX 2 | [2003/03/12 v1.1 MiKTeX 'graphics' configuration] 3 | 4 | % Select an appropriate default driver 5 | \begingroup 6 | \chardef\x=0 % 7 | % check pdfTeX 8 | \@ifundefined{pdfoutput}{}{% 9 | \ifcase\pdfoutput 10 | \else 11 | \chardef\x=1 % 12 | \fi 13 | }% 14 | \expandafter\endgroup 15 | \ifcase\x 16 | % default case 17 | \ExecuteOptions{dvips}% 18 | \else 19 | % pdfTeX is running in pdf mode 20 | \ExecuteOptions{pdftex}% 21 | \fi 22 | 23 | % Fix for dvips and xdvi versions that can uncompress 24 | % graphic files without an explicite call of gunzip. 25 | % (The fix is not applied for miniltx.tex, because 26 | % \AtEndOfPackage is not available in plainTeX.) 27 | \endinput 28 | -------------------------------------------------------------------------------- /05_dynprog/problems.cls: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e} 2 | \ProvidesClass{problems}[2006/11/03] 3 | 4 | % identification 5 | % initial code 6 | % declaration of options 7 | % execution of options 8 | % package loading 9 | % main code 10 | 11 | % Declaration of Options 12 | \DeclareOption{draft}{\PassOptionsToClass{draft}{article}\AtEndOfClass{\geometry{showframe}}} 13 | \DeclareOption{10pt}{\PassOptionsToClass{10pt}{article}} 14 | \DeclareOption{11pt}{\PassOptionsToClass{11pt}{article}} 15 | \DeclareOption{12pt}{\PassOptionsToClass{12pt}{article}} 16 | 17 | \hfuzz=0.1cm 18 | 19 | % Опцию a4paper будем использовать для формата, в котором задачки 20 | % печатались раньше на бумаге A4. 21 | \DeclareOption{a4paper}{ 22 | \PassOptionsToPackage{a4paper,includehead,includefoot,headheight=10pt,headsep=2mm,width=17cm,height=27cm,footskip=0.5cm}{geometry} 23 | } 24 | 25 | % Execution of Options 26 | \ProcessOptions\relax 27 | 28 | % Package Loading 29 | \LoadClass[a4paper]{article} 30 | 31 | \RequirePackage[T2A]{fontenc} 32 | \RequirePackage[utf8]{inputenc} 33 | \RequirePackage{mathtext} 34 | \RequirePackage[english,russian]{babel} 35 | \RequirePackage[dvips,final]{graphicx} 36 | \RequirePackage{wrapfig} 37 | \RequirePackage{amssymb} 38 | \RequirePackage{amsmath} 39 | \RequirePackage{amscd} 40 | \RequirePackage{array} 41 | \RequirePackage{multicol} 42 | \RequirePackage{longtable} 43 | \RequirePackage[dvips]{geometry} 44 | 45 | % Main Code 46 | \columnseprule=0.4pt 47 | \raggedbottom 48 | 49 | 50 | % AK: думаю, лучше везде использовать вариант "". 51 | %\declare@shorthand{russian}{""}{\nobreak\hskip.2em\ignorespaces} 52 | %\declare@shorthand{russian}{",}{\nobreak\hskip.2em\ignorespaces} 53 | % KAP: чтобы кавычки всегда были правильные 54 | %\declare@shorthand{russian}{"<}{<<} 55 | %\declare@shorthand{russian}{">}{>>} 56 | %---------- From package "lastpage" ------------------ 57 | \def\lastpage@putlabel{\addtocounter{page}{-1}% 58 | \immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}% 59 | \addtocounter{page}{1}} 60 | \AtEndDocument{\clearpage\lastpage@putlabel}% 61 | %---------- end of "lastpage" ------------------ 62 | 63 | \newcommand{\headernono}[1]{% 64 | \par\pagebreak[2]\vspace{1.5ex plus1ex minus .7ex}% 65 | \noindent{\large\bf\sffamily\strut #1}\par 66 | \nopagebreak\vspace{.8ex plus.8ex minus.3ex}% 67 | } 68 | 69 | \newcounter{headercount} 70 | \renewcommand{\theheadercount}{\Roman{headercount}} 71 | \newcommand{\header}[1]{% 72 | \refstepcounter{headercount}\headernono{Часть \Roman{headercount}. #1} 73 | } 74 | 75 | \newcounter{lheadercount}[headercount] 76 | \renewcommand{\thelheadercount}{\theheadercount.\arabic{lheadercount}} 77 | \newcommand{\lheader}[1]{% 78 | \par\pagebreak[3]\vspace{0.5ex plus1ex}% 79 | \refstepcounter{lheadercount}{\bf \S\arabic{lheadercount}. #1.}% 80 | } 81 | 82 | \newcommand{\Header}[1]{% 83 | \par\pagebreak[2]\vspace{2.7ex plus 1.3ex minus 1.3ex}% 84 | \noindent{\Large\bf\sffamily #1}\par 85 | \nopagebreak\vspace{2ex plus 1ex minus 1ex}% 86 | } 87 | 88 | \newcounter{llheadercount}[lheadercount] 89 | \renewcommand{\thellheadercount}{\thelheadercount.\arabic{llheadercount}} 90 | \newcommand{\llheader}{% 91 | \par\pagebreak[3]% 92 | \refstepcounter{llheadercount}{\bf \arabic{llheadercount}.} % 93 | } 94 | 95 | %\def\nought{\ensuremath{{\mkern-3.25mu{\not}\mkern3.25mu\mbox{\tt0}}}} 96 | \def\slnought{{\tt\O}} 97 | 98 | \newcommand{\todo}[1]{\marginpar{\raggedright\footnotesize!~TODO:\\#1}} 99 | 100 | \renewcommand{\@oddhead}{} 101 | 102 | \renewcommand{\@oddfoot}{% 103 | \vbox{% 104 | \hrule\vspace{0.1cm}% 105 | \hbox to \textwidth{% 106 | \sf\footnotesize% 107 | \hfill\strut Страница \thepage\ из \pageref{LastPage}\hfill% 108 | }}} 109 | 110 | \renewcommand{\leq}{\leqslant} 111 | \renewcommand{\le}{\leqslant} 112 | \renewcommand{\geq}{\geqslant} 113 | 114 | \newcommand{\unit}[1]{\mbox{ \rm #1}} 115 | % \vstring#1 116 | % Написать #1 как строку вх/вых файла (в кавычках шрифтом \tt без 117 | % переносов) 118 | \newcommand*{\vstring}[1]{`\mbox{\tt#1}'} 119 | 120 | %БАГ: пока не работает генерация автоматических ссылок на пункты перечня 121 | \newcounter{tmp} 122 | 123 | \newenvironment{ulists}[2]{% 124 | \begin{list}{#1}{\topsep=0.6ex plus 0.3ex minus 0.6ex \partopsep=0.6ex minus 0.6ex \parsep=0pt \itemsep=0pt #2}% 125 | } 126 | {\end{list}} 127 | 128 | \newenvironment{ulist}{% 129 | \begin{ulists}{$\bullet$}{}% 130 | } 131 | {\end{ulists}} 132 | 133 | \newenvironment{olist}{% 134 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 135 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{}% 136 | } 137 | {\end{ulists}} 138 | 139 | \newenvironment{olistzero}{% 140 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 141 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \partopsep=0ex}% 142 | } 143 | {\end{ulists}} 144 | 145 | \newenvironment{wideolist}{% 146 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 147 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \parsep=0pt \itemsep=0pt \leftmargin=0pt \itemindent=\labelwidth}% 148 | } 149 | {\end{ulists}} 150 | 151 | % Нумерованный список с сквозной нумерацией 152 | \newcounter{olistcount}\renewcommand{\theolistcount}{\arabic{olistcount}} 153 | \newcommand{\resetolist}{\setcounter{olistcount}{0}} 154 | \newenvironment{olistc}{% 155 | \renewcommand{\theolistcount}{\arabic{olistcount}} 156 | \begin{ulists}{\refstepcounter{olistcount}\theolistcount.}{}% 157 | } 158 | {\end{ulists}} 159 | 160 | % Нумерованный список для использования в тексте, когда каждый пункт 161 | % пишется с маленькой буквы и отделяется ";". 162 | % Здесь помечается арабской цифрой со скобкой. 163 | \newenvironment{tllist}{% 164 | \setcounter{tmp}{0} 165 | \begin{ulists}{\refstepcounter{tmp}\thetmp)}{}% 166 | } 167 | {\end{ulists}} 168 | 169 | \newcommand*{\hm}[1]{#1\nobreak\discretionary{}{\hbox{$\mathsurround=0pt #1$}}{}} 170 | 171 | \newcommand{\wvec}[1]{\overrightarrow{#1}} 172 | 173 | \newcommand{\wnote}[1]{{\sl [~#1~]\todo{!}}} 174 | 175 | \relpenalty=10000 176 | \binoppenalty=10000 177 | 178 | \newcommand{\OR}{\mathrel{\mathrm{or}}} 179 | \newcommand{\XOR}{\mathrel{\mathrm{xor}}} 180 | \newcommand{\AND}{\mathrel{\mathrm{and}}} 181 | \newcommand{\NOT}{\mathop{\mathrm{not}}} 182 | \newcommand{\SHL}{\mathop{\mathrm{shl}}} 183 | \newcommand{\SHR}{\mathop{\mathrm{shr}}} 184 | 185 | 186 | % Суммарная ширина столбцов в двухколоночной таблице, выровненной по ширине 187 | \newlength\twowidth 188 | \newcommand{\settwowidth}{ 189 | \twowidth=\textwidth 190 | \addtolength\twowidth{-4\tabcolsep} 191 | \addtolength\twowidth{-3\arrayrulewidth} 192 | } 193 | \AtBeginDocument{\settwowidth}%т.к. \textwidth надо сначала установить 194 | 195 | % --= поддержка примеров программ, сделаных conv.pas =-- 196 | % Это для борьбы с разрывами страницы после окружений multicols 197 | \newlength{\cs@topskip} 198 | \newlength{\cs@bottom} 199 | \newlength{\cs@bottomback} 200 | \newlength{\cs@top} 201 | \cs@topskip=1.5ex 202 | \cs@bottom=1.5ex 203 | \cs@bottomback=1ex plus 0.5ex minus 0.3ex 204 | \footnotesize\cs@top=2.4ex\normalsize 205 | 206 | \newenvironment{codesamplec}[1] 207 | {% локальные определения: 208 | \newcommand{\codelf}{\kern-1.5em\\}% 209 | \newcommand{\codespace}{{\ttfamily\symbol{`\ }}}% 210 | \newcommand{\codetok}[1]{{\bfseries##1}}% 211 | \newcommand{\codecmt}[1]{{\ttfamily\slshape##1}}% 212 | \vspace{0.5ex plus 0.3ex minus 0.1ex} 213 | \topskip=\cs@topskip%KAP: не знаю почему, но работает :):):) !!! От этого параметра зависимость --- пороговая. Пришлось еще подрегулировать \vspace строкой ниже 214 | %KAP: тут где-то еще видимо затесался vspace с plus/minus компонентой, так что, если сильно ужимать страницу, то все переедет... 215 | \par\begin{multicols}{#1}[\footnotesize\hrule\nopagebreak\vspace{-\cs@top}]\tt\noindent} 216 | {\end{multicols}\par\vspace*{-\cs@bottom}\hrule\vspace*{\cs@bottomback}\pagebreak[0]} 217 | 218 | \newenvironment{codesample}{\begin{codesamplec}{2}}{\end{codesamplec}} 219 | 220 | \newenvironment{codesampleo} 221 | {\vspace{0.5ex plus 0.3ex minus 0.1ex} 222 | \par\footnotesize\hrule\nopagebreak\vspace{-1.3ex}\tt\noindent} 223 | {\par\nopagebreak\vspace{-1.3ex}\hrule\vspace{\cs@bottomback}} 224 | 225 | % --= * =-- 226 | 227 | \newcommand{\noten}[2]{{\vspace{0.1cm}\par\pagebreak[3]\small \textit{#1:} #2 \vspace{0.1cm plus 0.1cm}\par}} 228 | \newcommand{\note}[1]{\noten{Примечание}{#1}} 229 | 230 | \newcommand{\eps}{\varepsilon} 231 | 232 | \newcommand{\epigraph}[2]{%\hangindent=0.4\textwidth\begin{flushright}\small\textit{#1}\par\footnotesize#2\par\end{flushright} 233 | {\parindent=0cm 234 | \parshape 1 0.4\textwidth 0.6\textwidth 235 | \begin{flushright}% 236 | \small\textit{#1}\par% 237 | \vspace{0.1cm}% 238 | \footnotesize#2\par% 239 | \end{flushright}}% 240 | } 241 | 242 | \newcounter{taskcount} 243 | \renewcommand{\thetaskcount}{\arabic{taskcount}} 244 | \newcommand{\taskon}[2]{% 245 | \refstepcounter{taskcount}% 246 | \textbf{#1\mbox{~}\thetaskcount:} {\it #2}% 247 | } 248 | \newcommand{\tasko}[1]{\taskon{Задание}{#1}} 249 | 250 | \newcommand{\hint}[2]{\textbf{Посказка \ref{#1}:} #2} 251 | 252 | \newcommand{\answer}[2]{\textbf{Ответ \ref{#1}:} #2} 253 | 254 | \renewcommand{\ddots}{\,\,.\,.\,\,} 255 | 256 | %ANSWERS + 257 | \newlinechar=`\^^M 258 | 259 | \newwrite\tsk 260 | \immediate\openout\tsk=\jobname.tsk\relax 261 | \newwrite\ans 262 | \immediate\openout\ans=\jobname.ans\relax 263 | \newwrite\hnt 264 | \immediate\openout\hnt=\jobname.hnt\relax 265 | \newwrite\dup 266 | 267 | \def\makerusother{% 268 | \@tempcnta128\relax% 269 | \loop% 270 | \catcode\@tempcnta12% 271 | \ifnum\@tempcnta<255\relax% 272 | \advance\@tempcnta\@ne% 273 | \repeat% 274 | } 275 | 276 | \def\makeallother{% 277 | \let\do\@makeother\dospecials% 278 | \makerusother% 279 | } 280 | 281 | \def\writeansno#1#2{% 282 | \begingroup% 283 | \makeallother% 284 | \obeylines% 285 | \long\def\copyans#2##1#2{% 286 | \def\tmp{##1}% 287 | \if\tmp\empty% 288 | \else% 289 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 290 | \immediate\write#1{##1}% 291 | \fi% 292 | \endgroup\afterwriteans% 293 | }% 294 | \copyans#2% 295 | } 296 | 297 | \def\dupeans#1#2{% 298 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 299 | \immediate\openout\dup=\jobname.dup\relax% 300 | \begingroup% 301 | \makeallother% 302 | \obeylines% 303 | \long\def\copyans#2##1#2{% 304 | \immediate\write#1{##1}% 305 | \immediate\write\dup{##1\noexpand\endinput}% 306 | \endgroup\immediate\closeout\dup% 307 | \input{\jobname.dup}% 308 | \afterwriteans% 309 | }% 310 | \copyans#2% 311 | } 312 | 313 | \def\tasknn#1{% 314 | \endgroup% 315 | \refstepcounter{taskcount}% 316 | \gdef\taskname{#1}% 317 | \immediate\openout\dup=\jobname.dup\relax% 318 | \immediate\write\dup{\noexpand\taskcaption{\taskname{}\noexpand~\thetaskcount:}\noexpand\endinput}% 319 | \immediate\closeout\dup% 320 | \input{\jobname.dup}% 321 | \let\afterwriteans\relax% 322 | \gdef\afterwriteans{% 323 | \gdef\afterwriteans{% 324 | \let\afterwriteans\endgroup% 325 | \writeansno\ans% 326 | }% 327 | \writeansno\hnt% 328 | } 329 | \begingroup\it% 330 | \dupeans\tsk% 331 | } 332 | 333 | \def\taskn{% 334 | \begingroup\makerusother\tasknn% 335 | } 336 | 337 | {\makerusother 338 | \gdef\deftaskname{Задание} 339 | } 340 | 341 | \def\task{\taskn{\deftaskname}} 342 | 343 | \def\taskcaption#1{\textbf{#1}} 344 | 345 | \long\def\answer#1#2{ 346 | \par\pagebreak[3]\mbox{\taskcaption{#1} (стр. #2):} 347 | } 348 | 349 | \def\inputanswers{% 350 | \immediate\closeout\tsk 351 | \immediate\closeout\hnt 352 | \immediate\closeout\ans 353 | \eject\header{Условия всех задач} 354 | \input{\jobname.tsk} 355 | \eject\header{Подсказки} 356 | \input{\jobname.hnt} 357 | \eject\header{Ответы} 358 | \input{\jobname.ans} 359 | } 360 | 361 | -------------------------------------------------------------------------------- /05_dynprog/problems_ans.cls: -------------------------------------------------------------------------------- 1 | 2 | %ANSWERS + 3 | \newlinechar=`\^^M 4 | 5 | \newwrite\tsk 6 | \immediate\openout\tsk=\jobname.tsk\relax 7 | \newwrite\ans 8 | \immediate\openout\ans=\jobname.ans\relax 9 | \newwrite\hnt 10 | \immediate\openout\hnt=\jobname.hnt\relax 11 | \newwrite\dup 12 | 13 | \def\makerusother{% 14 | \@tempcnta128\relax% 15 | \loop% 16 | \catcode\@tempcnta12% 17 | \ifnum\@tempcnta<255\relax% 18 | \advance\@tempcnta\@ne% 19 | \repeat% 20 | } 21 | 22 | \def\makeallother{% 23 | \let\do\@makeother\dospecials% 24 | \makerusother% 25 | } 26 | 27 | \def\writeansno#1#2{% 28 | \begingroup% 29 | \makeallother% 30 | \obeylines% 31 | \long\def\copyans#2##1#2{% 32 | \def\tmp{##1}% 33 | \if\tmp\empty% 34 | \else% 35 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 36 | \immediate\write#1{##1}% 37 | \fi% 38 | \endgroup\afterwriteans% 39 | }% 40 | \copyans#2% 41 | } 42 | 43 | \def\dupeans#1#2{% 44 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 45 | \immediate\openout\dup=\jobname.dup\relax% 46 | \begingroup% 47 | \makeallother% 48 | \obeylines% 49 | \long\def\copyans#2##1#2{% 50 | \immediate\write#1{##1}% 51 | \immediate\write\dup{##1\noexpand\endinput}% 52 | \endgroup\immediate\closeout\dup% 53 | \input{\jobname.dup}% 54 | \afterwriteans% 55 | }% 56 | \copyans#2% 57 | } 58 | 59 | \def\tasknn#1{% 60 | \endgroup% 61 | \refstepcounter{taskcount}% 62 | \gdef\taskname{#1}% 63 | \immediate\openout\dup=\jobname.dup\relax% 64 | \immediate\write\dup{\noexpand\taskcaption{\taskname{}\noexpand~\thetaskcount:}\noexpand\endinput}% 65 | \immediate\closeout\dup% 66 | \input{\jobname.dup}% 67 | \let\afterwriteans\relax% 68 | \gdef\afterwriteans{% 69 | \gdef\afterwriteans{% 70 | \let\afterwriteans\endgroup% 71 | \writeansno\ans% 72 | }% 73 | \writeansno\hnt% 74 | } 75 | \begingroup\it% 76 | \dupeans\tsk% 77 | } 78 | 79 | \def\taskn{% 80 | \begingroup\makerusother\tasknn% 81 | } 82 | 83 | {\makerusother 84 | \gdef\deftaskname{Задание} 85 | } 86 | 87 | \def\task{\taskn{\deftaskname}} 88 | 89 | \def\taskcaption#1{\textbf{#1}} 90 | 91 | \long\def\answer#1#2{ 92 | \par\pagebreak[3]\mbox{\taskcaption{#1} (стр. #2):} 93 | } 94 | 95 | \def\inputanswers{% 96 | \immediate\closeout\tsk 97 | \immediate\closeout\hnt 98 | \immediate\closeout\ans 99 | \eject\header{Условия всех задач} 100 | \input{\jobname.tsk} 101 | \eject\header{Подсказки} 102 | \input{\jobname.hnt} 103 | \eject\header{Ответы} 104 | \input{\jobname.ans} 105 | } 106 | 107 | -------------------------------------------------------------------------------- /05_dynprog/texts/05_2_fundamental/graph.mp: -------------------------------------------------------------------------------- 1 | prologues:=0; 2 | 3 | dx:=1.5cm; 4 | dy:=1cm; 5 | levmax:=3; 6 | input TEX.mp 7 | pw:=0.2cm; 8 | path box; 9 | 10 | def drawgraph(expr i,j,x,y,lev)= 11 | numeric xx,yy; 12 | 13 | if lev 2 | #include 3 | using namespace std; 4 | 5 | vector* foo(int n) { 6 | vector a; 7 | a.resize(4); 8 | a[0] = n; 9 | for (int i=1; i<=n; i++) 10 | a[i] = a[i-1] + i; 11 | return &a; 12 | } 13 | 14 | int main() { 15 | int n; 16 | cin >> n; 17 | vector *b = foo(n); 18 | cout << (*b)[n] << endl; 19 | return 0; 20 | } -------------------------------------------------------------------------------- /06_testing/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::cout << 19999.99 << std::endl; 5 | } -------------------------------------------------------------------------------- /06_testing/do.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | latex 06_testing.tex 3 | dvipdfmx -p a4 06_testing.dvi -------------------------------------------------------------------------------- /06_testing/graphics.cfg: -------------------------------------------------------------------------------- 1 | \ProvidesFile{graphics.cfg}% stolen from TL/teTeX 2 | [2003/03/12 v1.1 MiKTeX 'graphics' configuration] 3 | 4 | % Select an appropriate default driver 5 | \begingroup 6 | \chardef\x=0 % 7 | % check pdfTeX 8 | \@ifundefined{pdfoutput}{}{% 9 | \ifcase\pdfoutput 10 | \else 11 | \chardef\x=1 % 12 | \fi 13 | }% 14 | \expandafter\endgroup 15 | \ifcase\x 16 | % default case 17 | \ExecuteOptions{dvips}% 18 | \else 19 | % pdfTeX is running in pdf mode 20 | \ExecuteOptions{pdftex}% 21 | \fi 22 | 23 | % Fix for dvips and xdvi versions that can uncompress 24 | % graphic files without an explicite call of gunzip. 25 | % (The fix is not applied for miniltx.tex, because 26 | % \AtEndOfPackage is not available in plainTeX.) 27 | \endinput 28 | -------------------------------------------------------------------------------- /06_testing/problems.cls: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e} 2 | \ProvidesClass{problems}[2006/11/03] 3 | 4 | % identification 5 | % initial code 6 | % declaration of options 7 | % execution of options 8 | % package loading 9 | % main code 10 | 11 | % Declaration of Options 12 | \DeclareOption{draft}{\PassOptionsToClass{draft}{article}\AtEndOfClass{\geometry{showframe}}} 13 | \DeclareOption{10pt}{\PassOptionsToClass{10pt}{article}} 14 | \DeclareOption{11pt}{\PassOptionsToClass{11pt}{article}} 15 | \DeclareOption{12pt}{\PassOptionsToClass{12pt}{article}} 16 | 17 | \hfuzz=0.1cm 18 | 19 | % Опцию a4paper будем использовать для формата, в котором задачки 20 | % печатались раньше на бумаге A4. 21 | \DeclareOption{a4paper}{ 22 | \PassOptionsToPackage{a4paper,includehead,includefoot,headheight=10pt,headsep=2mm,width=17cm,height=27cm,footskip=0.5cm}{geometry} 23 | } 24 | 25 | % Execution of Options 26 | \ProcessOptions\relax 27 | 28 | % Package Loading 29 | \LoadClass[a4paper]{article} 30 | 31 | \RequirePackage[T2A]{fontenc} 32 | \RequirePackage[utf8]{inputenc} 33 | \RequirePackage{mathtext} 34 | \RequirePackage[english,russian]{babel} 35 | \RequirePackage[dvips,final]{graphicx} 36 | \RequirePackage{wrapfig} 37 | \RequirePackage{amssymb} 38 | \RequirePackage{amsmath} 39 | \RequirePackage{amscd} 40 | \RequirePackage{array} 41 | \RequirePackage{multicol} 42 | \RequirePackage{longtable} 43 | \RequirePackage[dvips]{geometry} 44 | 45 | % Main Code 46 | \columnseprule=0.4pt 47 | \raggedbottom 48 | 49 | 50 | % AK: думаю, лучше везде использовать вариант "". 51 | %\declare@shorthand{russian}{""}{\nobreak\hskip.2em\ignorespaces} 52 | %\declare@shorthand{russian}{",}{\nobreak\hskip.2em\ignorespaces} 53 | % KAP: чтобы кавычки всегда были правильные 54 | %\declare@shorthand{russian}{"<}{<<} 55 | %\declare@shorthand{russian}{">}{>>} 56 | %---------- From package "lastpage" ------------------ 57 | \def\lastpage@putlabel{\addtocounter{page}{-1}% 58 | \immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}% 59 | \addtocounter{page}{1}} 60 | \AtEndDocument{\clearpage\lastpage@putlabel}% 61 | %---------- end of "lastpage" ------------------ 62 | 63 | \newcommand{\headernono}[1]{% 64 | \par\pagebreak[2]\vspace{1.5ex plus1ex minus .7ex}% 65 | \noindent{\large\bf\sffamily\strut #1}\par 66 | \nopagebreak\vspace{.8ex plus.8ex minus.3ex}% 67 | } 68 | 69 | \newcounter{headercount} 70 | \renewcommand{\theheadercount}{\Roman{headercount}} 71 | \newcommand{\header}[1]{% 72 | \refstepcounter{headercount}\headernono{Часть \Roman{headercount}. #1} 73 | } 74 | 75 | \newcounter{lheadercount}[headercount] 76 | \renewcommand{\thelheadercount}{\theheadercount.\arabic{lheadercount}} 77 | 78 | \newcommand{\lheadernd}[1]{% 79 | \par\pagebreak[3]\vspace{0.5ex plus1ex}% 80 | \refstepcounter{lheadercount}{\bf \arabic{lheadercount}. #1}% 81 | } 82 | \newcommand{\lheader}[1]{% 83 | \lheadernd{#1.}% 84 | } 85 | 86 | \newcommand{\Header}[1]{% 87 | \par\pagebreak[2]\vspace{2.7ex plus 1.3ex minus 1.3ex}% 88 | \noindent{\Large\bf\sffamily #1}\par 89 | \nopagebreak\vspace{2ex plus 1ex minus 1ex}% 90 | } 91 | 92 | \newcounter{llheadercount}[lheadercount] 93 | \renewcommand{\thellheadercount}{\thelheadercount.\arabic{llheadercount}} 94 | \newcommand{\llheader}{% 95 | \par\pagebreak[3]% 96 | \refstepcounter{llheadercount}{\bf \arabic{llheadercount}.} % 97 | } 98 | 99 | %\def\nought{\ensuremath{{\mkern-3.25mu{\not}\mkern3.25mu\mbox{\tt0}}}} 100 | \def\slnought{{\tt\O}} 101 | 102 | \newcommand{\todo}[1]{\marginpar{\raggedright\footnotesize!~TODO:\\#1}} 103 | 104 | \renewcommand{\@oddhead}{} 105 | 106 | \renewcommand{\@oddfoot}{% 107 | \vbox{% 108 | \hrule\vspace{0.1cm}% 109 | \hbox to \textwidth{% 110 | \sf\footnotesize% 111 | \hfill\strut Страница \thepage\ из \pageref{LastPage}\hfill% 112 | }}} 113 | 114 | \renewcommand{\leq}{\leqslant} 115 | \renewcommand{\le}{\leqslant} 116 | \renewcommand{\geq}{\geqslant} 117 | 118 | \newcommand{\unit}[1]{\mbox{ \rm #1}} 119 | % \vstring#1 120 | % Написать #1 как строку вх/вых файла (в кавычках шрифтом \tt без 121 | % переносов) 122 | \newcommand*{\vstring}[1]{`\mbox{\tt#1}'} 123 | 124 | %БАГ: пока не работает генерация автоматических ссылок на пункты перечня 125 | \newcounter{tmp} 126 | 127 | \newenvironment{ulists}[2]{% 128 | \begin{list}{#1}{\topsep=0.6ex plus 0.3ex minus 0.6ex \partopsep=0.6ex minus 0.6ex \parsep=0pt \itemsep=0pt #2}% 129 | } 130 | {\end{list}} 131 | 132 | \newenvironment{ulist}{% 133 | \begin{ulists}{$\bullet$}{}% 134 | } 135 | {\end{ulists}} 136 | 137 | \newenvironment{olist}{% 138 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 139 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{}% 140 | } 141 | {\end{ulists}} 142 | 143 | \newenvironment{olistzero}{% 144 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 145 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \partopsep=0ex}% 146 | } 147 | {\end{ulists}} 148 | 149 | \newenvironment{wideolist}{% 150 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 151 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \parsep=0pt \itemsep=0pt \leftmargin=0pt \itemindent=\labelwidth}% 152 | } 153 | {\end{ulists}} 154 | 155 | % Нумерованный список с сквозной нумерацией 156 | \newcounter{olistcount}\renewcommand{\theolistcount}{\arabic{olistcount}} 157 | \newcommand{\resetolist}{\setcounter{olistcount}{0}} 158 | \newenvironment{olistc}{% 159 | \renewcommand{\theolistcount}{\arabic{olistcount}} 160 | \begin{ulists}{\refstepcounter{olistcount}\theolistcount.}{}% 161 | } 162 | {\end{ulists}} 163 | 164 | % Нумерованный список для использования в тексте, когда каждый пункт 165 | % пишется с маленькой буквы и отделяется ";". 166 | % Здесь помечается арабской цифрой со скобкой. 167 | \newenvironment{tllist}{% 168 | \setcounter{tmp}{0} 169 | \begin{ulists}{\refstepcounter{tmp}\thetmp)}{}% 170 | } 171 | {\end{ulists}} 172 | 173 | \newcommand*{\hm}[1]{#1\nobreak\discretionary{}{\hbox{$\mathsurround=0pt #1$}}{}} 174 | 175 | \newcommand{\wvec}[1]{\overrightarrow{#1}} 176 | 177 | \newcommand{\wnote}[1]{{\sl [~#1~]\todo{!}}} 178 | 179 | \relpenalty=10000 180 | \binoppenalty=10000 181 | 182 | \newcommand{\OR}{\mathrel{\mathrm{or}}} 183 | \newcommand{\XOR}{\mathrel{\mathrm{xor}}} 184 | \newcommand{\AND}{\mathrel{\mathrm{and}}} 185 | \newcommand{\NOT}{\mathop{\mathrm{not}}} 186 | \newcommand{\SHL}{\mathop{\mathrm{shl}}} 187 | \newcommand{\SHR}{\mathop{\mathrm{shr}}} 188 | 189 | 190 | % Суммарная ширина столбцов в двухколоночной таблице, выровненной по ширине 191 | \newlength\twowidth 192 | \newcommand{\settwowidth}{ 193 | \twowidth=\textwidth 194 | \addtolength\twowidth{-4\tabcolsep} 195 | \addtolength\twowidth{-3\arrayrulewidth} 196 | } 197 | \AtBeginDocument{\settwowidth}%т.к. \textwidth надо сначала установить 198 | 199 | % --= поддержка примеров программ, сделаных conv.pas =-- 200 | % Это для борьбы с разрывами страницы после окружений multicols 201 | \newlength{\cs@topskip} 202 | \newlength{\cs@bottom} 203 | \newlength{\cs@bottomback} 204 | \newlength{\cs@top} 205 | \cs@topskip=1.5ex 206 | \cs@bottom=1.5ex 207 | \cs@bottomback=1ex plus 0.5ex minus 0.3ex 208 | \footnotesize\cs@top=2.4ex\normalsize 209 | 210 | \newenvironment{codesamplec}[1] 211 | {% локальные определения: 212 | \newcommand{\codelf}{\kern-1.5em\\}% 213 | \newcommand{\codespace}{{\ttfamily\symbol{`\ }}}% 214 | \newcommand{\codetok}[1]{{\bfseries##1}}% 215 | \newcommand{\codecmt}[1]{{\ttfamily\slshape##1}}% 216 | \vspace{0.5ex plus 0.3ex minus 0.1ex} 217 | \topskip=\cs@topskip%KAP: не знаю почему, но работает :):):) !!! От этого параметра зависимость --- пороговая. Пришлось еще подрегулировать \vspace строкой ниже 218 | %KAP: тут где-то еще видимо затесался vspace с plus/minus компонентой, так что, если сильно ужимать страницу, то все переедет... 219 | \par\begin{multicols}{#1}[\footnotesize\hrule\nopagebreak\vspace{-\cs@top}]\tt\noindent} 220 | {\end{multicols}\par\vspace*{-\cs@bottom}\hrule\vspace*{\cs@bottomback}\pagebreak[0]} 221 | 222 | \newenvironment{codesample}{\begin{codesamplec}{2}}{\end{codesamplec}} 223 | 224 | \newenvironment{codesampleo} 225 | {\vspace{0.5ex plus 0.3ex minus 0.1ex} 226 | \par\footnotesize\hrule\nopagebreak\vspace{-1.3ex}\tt\noindent} 227 | {\par\nopagebreak\vspace{-1.3ex}\hrule\vspace{\cs@bottomback}} 228 | 229 | % --= * =-- 230 | 231 | \newcommand{\noten}[2]{{\vspace{0.1cm}\par\pagebreak[3]\small \textit{#1:} #2 \vspace{0.1cm plus 0.1cm}\par}} 232 | \newcommand{\note}[1]{\noten{Примечание}{#1}} 233 | 234 | \newcommand{\eps}{\varepsilon} 235 | 236 | \newcommand{\epigraph}[2]{%\hangindent=0.4\textwidth\begin{flushright}\small\textit{#1}\par\footnotesize#2\par\end{flushright} 237 | {\parindent=0cm 238 | \parshape 1 0.4\textwidth 0.6\textwidth 239 | \begin{flushright}% 240 | \small\textit{#1}\par% 241 | \vspace{0.1cm}% 242 | \footnotesize#2\par% 243 | \end{flushright}}% 244 | } 245 | 246 | \newcounter{taskcount} 247 | \renewcommand{\thetaskcount}{\arabic{taskcount}} 248 | \newcommand{\taskon}[2]{% 249 | \refstepcounter{taskcount}% 250 | \textbf{#1\mbox{~}\thetaskcount:} {\it #2}% 251 | } 252 | \newcommand{\tasko}[1]{\taskon{Задание}{#1}} 253 | 254 | \newcommand{\hint}[2]{\textbf{Посказка \ref{#1}:} #2} 255 | 256 | \newcommand{\answer}[2]{\textbf{Ответ \ref{#1}:} #2} 257 | 258 | \renewcommand{\ddots}{\,\,.\,.\,\,} 259 | 260 | %ANSWERS + 261 | \newlinechar=`\^^M 262 | 263 | \newwrite\tsk 264 | \immediate\openout\tsk=\jobname.tsk\relax 265 | \newwrite\ans 266 | \immediate\openout\ans=\jobname.ans\relax 267 | \newwrite\hnt 268 | \immediate\openout\hnt=\jobname.hnt\relax 269 | \newwrite\dup 270 | 271 | \def\makerusother{% 272 | \@tempcnta128\relax% 273 | \loop% 274 | \catcode\@tempcnta12% 275 | \ifnum\@tempcnta<255\relax% 276 | \advance\@tempcnta\@ne% 277 | \repeat% 278 | } 279 | 280 | \def\makeallother{% 281 | \let\do\@makeother\dospecials% 282 | \makerusother% 283 | } 284 | 285 | \def\writeansno#1#2{% 286 | \begingroup% 287 | \makeallother% 288 | \obeylines% 289 | \long\def\copyans#2##1#2{% 290 | \def\tmp{##1}% 291 | \if\tmp\empty% 292 | \else% 293 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 294 | \immediate\write#1{##1}% 295 | \fi% 296 | \endgroup\afterwriteans% 297 | }% 298 | \copyans#2% 299 | } 300 | 301 | \def\dupeans#1#2{% 302 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 303 | \immediate\openout\dup=\jobname.dup\relax% 304 | \begingroup% 305 | \makeallother% 306 | \obeylines% 307 | \long\def\copyans#2##1#2{% 308 | \immediate\write#1{##1}% 309 | \immediate\write\dup{##1\noexpand\endinput}% 310 | \endgroup\immediate\closeout\dup% 311 | \input{\jobname.dup}% 312 | \afterwriteans% 313 | }% 314 | \copyans#2% 315 | } 316 | 317 | \def\tasknn#1{% 318 | \endgroup% 319 | \refstepcounter{taskcount}% 320 | \gdef\taskname{#1}% 321 | \immediate\openout\dup=\jobname.dup\relax% 322 | \immediate\write\dup{\noexpand\taskcaption{\taskname{}\noexpand~\thetaskcount:}\noexpand\endinput}% 323 | \immediate\closeout\dup% 324 | \input{\jobname.dup}% 325 | \let\afterwriteans\relax% 326 | \gdef\afterwriteans{% 327 | \gdef\afterwriteans{% 328 | \let\afterwriteans\endgroup% 329 | \writeansno\ans% 330 | }% 331 | \writeansno\hnt% 332 | } 333 | \begingroup\it% 334 | \dupeans\tsk% 335 | } 336 | 337 | \def\taskn{% 338 | \begingroup\makerusother\tasknn% 339 | } 340 | 341 | {\makerusother 342 | \gdef\deftaskname{Задание} 343 | } 344 | 345 | \def\task{\taskn{\deftaskname}} 346 | 347 | \def\taskcaption#1{\textbf{#1}} 348 | 349 | \long\def\answer#1#2{ 350 | \par\pagebreak[3]\mbox{\taskcaption{#1} (стр. #2):} 351 | } 352 | 353 | \def\inputanswers{% 354 | \immediate\closeout\tsk 355 | \immediate\closeout\hnt 356 | \immediate\closeout\ans 357 | \eject\header{Условия всех задач} 358 | \input{\jobname.tsk} 359 | \eject\header{Подсказки} 360 | \input{\jobname.hnt} 361 | \eject\header{Ответы} 362 | \input{\jobname.ans} 363 | } 364 | 365 | -------------------------------------------------------------------------------- /07_binsearch/07_binsearch.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \documentclass[a4paper,10pt]{problems} 5 | \usepackage{framed} 6 | \usepackage{verbatim} 7 | \let\eps\varepsilon 8 | 9 | 10 | \begin{document} 11 | 12 | 13 | \input{07_binsearch_main.tex} 14 | 15 | \end{document} 16 | -------------------------------------------------------------------------------- /07_binsearch/do.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | latex 07_binsearch.tex 3 | dvipdfmx -p a4 07_binsearch.dvi -------------------------------------------------------------------------------- /07_binsearch/problems.cls: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e} 2 | \ProvidesClass{problems}[2006/11/03] 3 | 4 | % identification 5 | % initial code 6 | % declaration of options 7 | % execution of options 8 | % package loading 9 | % main code 10 | 11 | % Declaration of Options 12 | \DeclareOption{draft}{\PassOptionsToClass{draft}{article}\AtEndOfClass{\geometry{showframe}}} 13 | \DeclareOption{10pt}{\PassOptionsToClass{10pt}{article}} 14 | \DeclareOption{11pt}{\PassOptionsToClass{11pt}{article}} 15 | \DeclareOption{12pt}{\PassOptionsToClass{12pt}{article}} 16 | 17 | \hfuzz=0.1cm 18 | 19 | % Опцию a4paper будем использовать для формата, в котором задачки 20 | % печатались раньше на бумаге A4. 21 | \DeclareOption{a4paper}{ 22 | \PassOptionsToPackage{a4paper,includehead,includefoot,headheight=10pt,headsep=2mm,width=17cm,height=27cm,footskip=0.5cm}{geometry} 23 | } 24 | 25 | % Execution of Options 26 | \ProcessOptions\relax 27 | 28 | % Package Loading 29 | \LoadClass[a4paper]{article} 30 | 31 | \RequirePackage[T2A]{fontenc} 32 | \RequirePackage[utf8]{inputenc} 33 | \RequirePackage{mathtext} 34 | \RequirePackage[english,russian]{babel} 35 | \RequirePackage[dvips,final]{graphicx} 36 | \RequirePackage{wrapfig} 37 | \RequirePackage{amssymb} 38 | \RequirePackage{amsmath} 39 | \RequirePackage{amscd} 40 | \RequirePackage{array} 41 | \RequirePackage{multicol} 42 | \RequirePackage{longtable} 43 | \RequirePackage[dvips]{geometry} 44 | 45 | % Main Code 46 | \columnseprule=0.4pt 47 | \raggedbottom 48 | 49 | 50 | % AK: думаю, лучше везде использовать вариант "". 51 | %\declare@shorthand{russian}{""}{\nobreak\hskip.2em\ignorespaces} 52 | %\declare@shorthand{russian}{",}{\nobreak\hskip.2em\ignorespaces} 53 | % KAP: чтобы кавычки всегда были правильные 54 | %\declare@shorthand{russian}{"<}{<<} 55 | %\declare@shorthand{russian}{">}{>>} 56 | %---------- From package "lastpage" ------------------ 57 | \def\lastpage@putlabel{\addtocounter{page}{-1}% 58 | \immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}% 59 | \addtocounter{page}{1}} 60 | \AtEndDocument{\clearpage\lastpage@putlabel}% 61 | %---------- end of "lastpage" ------------------ 62 | 63 | \newcommand{\headernono}[1]{% 64 | \par\pagebreak[2]\vspace{1.5ex plus1ex minus .7ex}% 65 | \noindent{\large\bf\sffamily\strut #1}\par 66 | \nopagebreak\vspace{.8ex plus.8ex minus.3ex}% 67 | } 68 | 69 | \newcounter{headercount} 70 | \renewcommand{\theheadercount}{\Roman{headercount}} 71 | \newcommand{\header}[1]{% 72 | \refstepcounter{headercount}\headernono{Часть \Roman{headercount}. #1} 73 | } 74 | 75 | \newcounter{lheadercount}[headercount] 76 | \renewcommand{\thelheadercount}{\theheadercount.\arabic{lheadercount}} 77 | 78 | \newcommand{\lheadernd}[1]{% 79 | \par\pagebreak[3]\vspace{0.5ex plus1ex}% 80 | \refstepcounter{lheadercount}{\bf \arabic{lheadercount}. #1}% 81 | } 82 | \newcommand{\lheader}[1]{% 83 | \lheadernd{#1.}% 84 | } 85 | 86 | \newcommand{\Header}[1]{% 87 | \par\pagebreak[2]\vspace{2.7ex plus 1.3ex minus 1.3ex}% 88 | \noindent{\Large\bf\sffamily #1}\par 89 | \nopagebreak\vspace{2ex plus 1ex minus 1ex}% 90 | } 91 | 92 | \newcounter{llheadercount}[lheadercount] 93 | \renewcommand{\thellheadercount}{\thelheadercount.\arabic{llheadercount}} 94 | \newcommand{\llheader}{% 95 | \par\pagebreak[3]% 96 | \refstepcounter{llheadercount}{\bf \arabic{llheadercount}.} % 97 | } 98 | 99 | %\def\nought{\ensuremath{{\mkern-3.25mu{\not}\mkern3.25mu\mbox{\tt0}}}} 100 | \def\slnought{{\tt\O}} 101 | 102 | \newcommand{\todo}[1]{\marginpar{\raggedright\footnotesize!~TODO:\\#1}} 103 | 104 | \renewcommand{\@oddhead}{} 105 | 106 | \renewcommand{\@oddfoot}{% 107 | \vbox{% 108 | \hrule\vspace{0.1cm}% 109 | \hbox to \textwidth{% 110 | \sf\footnotesize% 111 | \hfill\strut Страница \thepage\ из \pageref{LastPage}\hfill% 112 | }}} 113 | 114 | \renewcommand{\leq}{\leqslant} 115 | \renewcommand{\le}{\leqslant} 116 | \renewcommand{\geq}{\geqslant} 117 | 118 | \newcommand{\unit}[1]{\mbox{ \rm #1}} 119 | % \vstring#1 120 | % Написать #1 как строку вх/вых файла (в кавычках шрифтом \tt без 121 | % переносов) 122 | \newcommand*{\vstring}[1]{`\mbox{\tt#1}'} 123 | 124 | %БАГ: пока не работает генерация автоматических ссылок на пункты перечня 125 | \newcounter{tmp} 126 | 127 | \newenvironment{ulists}[2]{% 128 | \begin{list}{#1}{\topsep=0.6ex plus 0.3ex minus 0.6ex \partopsep=0.6ex minus 0.6ex \parsep=0pt \itemsep=0pt #2}% 129 | } 130 | {\end{list}} 131 | 132 | \newenvironment{ulist}{% 133 | \begin{ulists}{$\bullet$}{}% 134 | } 135 | {\end{ulists}} 136 | 137 | \newenvironment{olist}{% 138 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 139 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{}% 140 | } 141 | {\end{ulists}} 142 | 143 | \newenvironment{olistzero}{% 144 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 145 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \partopsep=0ex}% 146 | } 147 | {\end{ulists}} 148 | 149 | \newenvironment{wideolist}{% 150 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 151 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \parsep=0pt \itemsep=0pt \leftmargin=0pt \itemindent=\labelwidth}% 152 | } 153 | {\end{ulists}} 154 | 155 | % Нумерованный список с сквозной нумерацией 156 | \newcounter{olistcount}\renewcommand{\theolistcount}{\arabic{olistcount}} 157 | \newcommand{\resetolist}{\setcounter{olistcount}{0}} 158 | \newenvironment{olistc}{% 159 | \renewcommand{\theolistcount}{\arabic{olistcount}} 160 | \begin{ulists}{\refstepcounter{olistcount}\theolistcount.}{}% 161 | } 162 | {\end{ulists}} 163 | 164 | % Нумерованный список для использования в тексте, когда каждый пункт 165 | % пишется с маленькой буквы и отделяется ";". 166 | % Здесь помечается арабской цифрой со скобкой. 167 | \newenvironment{tllist}{% 168 | \setcounter{tmp}{0} 169 | \begin{ulists}{\refstepcounter{tmp}\thetmp)}{}% 170 | } 171 | {\end{ulists}} 172 | 173 | \newcommand*{\hm}[1]{#1\nobreak\discretionary{}{\hbox{$\mathsurround=0pt #1$}}{}} 174 | 175 | \newcommand{\wvec}[1]{\overrightarrow{#1}} 176 | 177 | \newcommand{\wnote}[1]{{\sl [~#1~]\todo{!}}} 178 | 179 | \relpenalty=10000 180 | \binoppenalty=10000 181 | 182 | \newcommand{\OR}{\mathrel{\mathrm{or}}} 183 | \newcommand{\XOR}{\mathrel{\mathrm{xor}}} 184 | \newcommand{\AND}{\mathrel{\mathrm{and}}} 185 | \newcommand{\NOT}{\mathop{\mathrm{not}}} 186 | \newcommand{\SHL}{\mathop{\mathrm{shl}}} 187 | \newcommand{\SHR}{\mathop{\mathrm{shr}}} 188 | 189 | 190 | % Суммарная ширина столбцов в двухколоночной таблице, выровненной по ширине 191 | \newlength\twowidth 192 | \newcommand{\settwowidth}{ 193 | \twowidth=\textwidth 194 | \addtolength\twowidth{-4\tabcolsep} 195 | \addtolength\twowidth{-3\arrayrulewidth} 196 | } 197 | \AtBeginDocument{\settwowidth}%т.к. \textwidth надо сначала установить 198 | 199 | % --= поддержка примеров программ, сделаных conv.pas =-- 200 | % Это для борьбы с разрывами страницы после окружений multicols 201 | \newlength{\cs@topskip} 202 | \newlength{\cs@bottom} 203 | \newlength{\cs@bottomback} 204 | \newlength{\cs@top} 205 | \cs@topskip=1.5ex 206 | \cs@bottom=1.5ex 207 | \cs@bottomback=1ex plus 0.5ex minus 0.3ex 208 | \footnotesize\cs@top=2.4ex\normalsize 209 | 210 | \newenvironment{codesamplec}[1] 211 | {% локальные определения: 212 | \newcommand{\codelf}{\kern-1.5em\\}% 213 | \newcommand{\codespace}{{\ttfamily\symbol{`\ }}}% 214 | \newcommand{\codetok}[1]{{\bfseries##1}}% 215 | \newcommand{\codecmt}[1]{{\ttfamily\slshape##1}}% 216 | \vspace{0.5ex plus 0.3ex minus 0.1ex} 217 | \topskip=\cs@topskip%KAP: не знаю почему, но работает :):):) !!! От этого параметра зависимость --- пороговая. Пришлось еще подрегулировать \vspace строкой ниже 218 | %KAP: тут где-то еще видимо затесался vspace с plus/minus компонентой, так что, если сильно ужимать страницу, то все переедет... 219 | \par\begin{multicols}{#1}[\footnotesize\hrule\nopagebreak\vspace{-\cs@top}]\tt\noindent} 220 | {\end{multicols}\par\vspace*{-\cs@bottom}\hrule\vspace*{\cs@bottomback}\pagebreak[0]} 221 | 222 | \newenvironment{codesample}{\begin{codesamplec}{2}}{\end{codesamplec}} 223 | 224 | \newenvironment{codesampleo} 225 | {\vspace{0.5ex plus 0.3ex minus 0.1ex} 226 | \par\footnotesize\hrule\nopagebreak\vspace{-1.3ex}\tt\noindent} 227 | {\par\nopagebreak\vspace{-1.3ex}\hrule\vspace{\cs@bottomback}} 228 | 229 | % --= * =-- 230 | 231 | \newcommand{\noten}[2]{{\vspace{0.1cm}\par\pagebreak[3]\small \textit{#1:} #2 \vspace{0.1cm plus 0.1cm}\par}} 232 | \newcommand{\note}[1]{\noten{Примечание}{#1}} 233 | 234 | \newcommand{\eps}{\varepsilon} 235 | 236 | \newcommand{\epigraph}[2]{%\hangindent=0.4\textwidth\begin{flushright}\small\textit{#1}\par\footnotesize#2\par\end{flushright} 237 | {\parindent=0cm 238 | \parshape 1 0.4\textwidth 0.6\textwidth 239 | \begin{flushright}% 240 | \small\textit{#1}\par% 241 | \vspace{0.1cm}% 242 | \footnotesize#2\par% 243 | \end{flushright}}% 244 | } 245 | 246 | \newcounter{taskcount} 247 | \renewcommand{\thetaskcount}{\arabic{taskcount}} 248 | \newcommand{\taskon}[2]{% 249 | \refstepcounter{taskcount}% 250 | \textbf{#1\mbox{~}\thetaskcount:} {\it #2}% 251 | } 252 | \newcommand{\tasko}[1]{\taskon{Задание}{#1}} 253 | 254 | \newcommand{\hint}[2]{\textbf{Посказка \ref{#1}:} #2} 255 | 256 | \newcommand{\answer}[2]{\textbf{Ответ \ref{#1}:} #2} 257 | 258 | \renewcommand{\ddots}{\,\,.\,.\,\,} 259 | 260 | %ANSWERS + 261 | \newlinechar=`\^^M 262 | 263 | \newwrite\tsk 264 | \immediate\openout\tsk=\jobname.tsk\relax 265 | \newwrite\ans 266 | \immediate\openout\ans=\jobname.ans\relax 267 | \newwrite\hnt 268 | \immediate\openout\hnt=\jobname.hnt\relax 269 | \newwrite\dup 270 | 271 | \def\makerusother{% 272 | \@tempcnta128\relax% 273 | \loop% 274 | \catcode\@tempcnta12% 275 | \ifnum\@tempcnta<255\relax% 276 | \advance\@tempcnta\@ne% 277 | \repeat% 278 | } 279 | 280 | \def\makeallother{% 281 | \let\do\@makeother\dospecials% 282 | \makerusother% 283 | } 284 | 285 | \def\writeansno#1#2{% 286 | \begingroup% 287 | \makeallother% 288 | \obeylines% 289 | \long\def\copyans#2##1#2{% 290 | \def\tmp{##1}% 291 | \if\tmp\empty% 292 | \else% 293 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 294 | \immediate\write#1{##1}% 295 | \fi% 296 | \endgroup\afterwriteans% 297 | }% 298 | \copyans#2% 299 | } 300 | 301 | \def\dupeans#1#2{% 302 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 303 | \immediate\openout\dup=\jobname.dup\relax% 304 | \begingroup% 305 | \makeallother% 306 | \obeylines% 307 | \long\def\copyans#2##1#2{% 308 | \immediate\write#1{##1}% 309 | \immediate\write\dup{##1\noexpand\endinput}% 310 | \endgroup\immediate\closeout\dup% 311 | \input{\jobname.dup}% 312 | \afterwriteans% 313 | }% 314 | \copyans#2% 315 | } 316 | 317 | \def\tasknn#1{% 318 | \endgroup% 319 | \refstepcounter{taskcount}% 320 | \gdef\taskname{#1}% 321 | \immediate\openout\dup=\jobname.dup\relax% 322 | \immediate\write\dup{\noexpand\taskcaption{\taskname{}\noexpand~\thetaskcount:}\noexpand\endinput}% 323 | \immediate\closeout\dup% 324 | \input{\jobname.dup}% 325 | \let\afterwriteans\relax% 326 | \gdef\afterwriteans{% 327 | \gdef\afterwriteans{% 328 | \let\afterwriteans\endgroup% 329 | \writeansno\ans% 330 | }% 331 | \writeansno\hnt% 332 | } 333 | \begingroup\it% 334 | \dupeans\tsk% 335 | } 336 | 337 | \def\taskn{% 338 | \begingroup\makerusother\tasknn% 339 | } 340 | 341 | {\makerusother 342 | \gdef\deftaskname{Задание} 343 | } 344 | 345 | \def\task{\taskn{\deftaskname}} 346 | 347 | \def\taskcaption#1{\textbf{#1}} 348 | 349 | \long\def\answer#1#2{ 350 | \par\pagebreak[3]\mbox{\taskcaption{#1} (стр. #2):} 351 | } 352 | 353 | \def\inputanswers{% 354 | \immediate\closeout\tsk 355 | \immediate\closeout\hnt 356 | \immediate\closeout\ans 357 | \eject\header{Условия всех задач} 358 | \input{\jobname.tsk} 359 | \eject\header{Подсказки} 360 | \input{\jobname.hnt} 361 | \eject\header{Ответы} 362 | \input{\jobname.ans} 363 | } 364 | 365 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Этот репозиторий и тесты устарели. Новая версия -- https://github.com/petr-kalinin/progtexts2 2 | 3 | # progtexts 4 | 5 | Это несколько текстов про различные алгоритмы, которые я писал, в основном, в 2008-2009 годах. С тех пор правка была весьма ограниченной. Часть текста, возможно, устарела. 6 | 7 | Если вы замечаете какие-либо ошибки, или у вас есть замечания или предложения, пишите мне (petr AT kalinin.nnov.ru), или — еще лучше — предлагайте pull requests. 8 | -------------------------------------------------------------------------------- /_all/algoprog.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \documentclass[a4paper,10pt]{problems} 5 | \usepackage{import} 6 | 7 | \begin{document} 8 | 9 | {\makerusother\relax 10 | \immediate\write\tsk{\noexpand\epigraph{\noexpand\dotsупражнений, которые настоятельно и, как всегда, 11 | безуспешно, рекомендую делать\noexpand\dots}{}} 12 | } 13 | 14 | \vbox to\textheight{ 15 | \thispagestyle{empty} 16 | \vfill\vfill 17 | \begin{center} 18 | \Huge\bf\textsf{Заметки\\ по алгоритмическому программированию} 19 | \end{center} 20 | 21 | \vfill 22 | 23 | \begin{flushright} 24 | Автор: Петр Калинин, 2008--2015\\ 25 | Этот документ можно распространять по лицензии\\ 26 | GNU General Public License версии 3 или более поздней.\\ 27 | Последнюю версию документа, а также исходный код для системы \LaTeX\\ 28 | можно скачать с \verb`https://github.com/petr-kalinin/progtexts`\\ 29 | \includegraphics[width=2cm]{gpl-by-christian-candena-cc-by.eps} 30 | \end{flushright} 31 | 32 | \vfill\vfill 33 | } 34 | 35 | \import{.}{licensing.tex} 36 | 37 | \tableofcontents 38 | 39 | \import{../00_fp/}{fp-quick-start.tex} 40 | \import{../01_backtrack/}{01_backtrack_main.tex} 41 | %\import{../02_complexity/}{02_complexity_main.tex} 42 | %\import{../03_shortideas/}{03_shortideas_main.tex} 43 | %\import{../04_dfs/}{04_dfs_main.tex} 44 | %\import{../05_dynprog/}{05_dynprog_main.tex} 45 | %\import{../06_testing/}{06_testing_main.tex} 46 | %\import{../07_binsearch/}{07_binsearch_main.tex} 47 | 48 | {\makerusother\relax 49 | \immediate\write\tsk{\noexpand\par\noexpand\vspace{0.5cm}\noexpand\epigraph{\noexpand\dotsВы не ужасайтесь\noexpand\dots{} реально все тривиально\noexpand\dots}{}} 50 | } 51 | 52 | 53 | \inputanswers 54 | 55 | \end{document} 56 | -------------------------------------------------------------------------------- /_all/do.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | pushd ../01_backtrack 3 | ./do_main.sh 4 | popd 5 | 6 | latex --shell-escape algoprog.tex 7 | dvipdfmx -p a4 algoprog.dvi 8 | -------------------------------------------------------------------------------- /_all/licensing.tex: -------------------------------------------------------------------------------- 1 | % Исходный LaTeX-код (c) Пётр Калинин 2 | % Код распространяется по лицензии GNU GPL (!) 3 | 4 | \headernono{О лицензии на эти заметки} 5 | \addcontentsline{toc}{section}{О лицензии на эти заметки} 6 | 7 | \small 8 | 9 | \epigraph{...право формулировать задачу и объяснять ее решение\\ является неотчуждаемым естественным правом всякого,\\ кто на это способен.}{А. Шень. Программирование: теоремы и задачи} 10 | 11 | Эти заметки вы можете бесплатно скачать на сайте \verb`https://github.com/petr-kalinin/progtexts` и использовать любыми законными способами. Я не беру денег за их использование и распространение, но, соответственно, \textit{требую}, чтобы и вы не ставили никаких ограничений на использование этого текста, если вы его куда-то дальше распространяете. Более того, с того же сайте вы можете свободно скачать и исходный код этих заметок для системы \LaTeX, и вы можете в него вносить изменения и/или использовать в своих работах, но я требую, чтобы в таком случае вы сделали свободным и исходный код ваших исправлений или тех работ, где вы используете текст этих заметок. 12 | 13 | А именно, я распространяю эти заметки на условиях лицензии GNU General Public License версии 3 (или, по вашему выбору, более старшей версии). Строгий текст лицензии вы можете прочитать на сайте Free Sofrware Foundation по адресу \verb`http://www.gnu.org/licenses/gpl-3.0.en.html` (неофициальный русский перевод: \verb`http://rus`\-\verb`gpl.ru/rusgpl.html`), или в файле \verb`COPYING.txt`, распространяемым вместе с \LaTeX-кодами этих заметок. Ниже я вкратце объясняю, что это обозначает; если вы знаете GNU GPL, то можете пропустить эти объяснения до раздела <<Дополнительные замечания>>. В частности, если вам интересно, почему я использую именно GNU GPL, а не CC~BY-SA или другую CC лицензию, то читайте раздел <<Дополнительные замечания>>. 14 | 15 | Итак, вы можете свободно использовать эти заметки при условии, что вы их не изменяете (в частности, сохраняете указание на мое авторство и указание на лицензию). Вы можете их также распространять (выставлять на сайте, распространять в печатном виде и т.п.) куда угодно на этих же условиях (т.е. по этой же лицензии). Кроме того, вы можете модифицировать эти заметки, а также использовать текст заметок в своих работах, на следующих условиях. Во-первых, вы должны распространять полученный текст (измененную версию этих заметок или свою собственную работу) также на условиях GNU GPL, в том числе не ограничивая дальнейшее распространение. Во-вторых, вы должны сделать свободно доступным на условиях GNU GPL <<\textit{исходный код}>> измененных заметок или вашей работы, т.е. тот формат, в котором вы сами вносили изменения и/или создавали свою работу. А именно, если вы правите исходный код \LaTeX, то вы должны сделать исправленный исходный код \LaTeX{} свободно доступным. Вы не можете распространять только полученный PDF или вообще только печатную версию, а исходный \LaTeX-код сделать закрытым. Или, если вы, к примеру, используете Photoshop для правки уже сгенерированного PDF, то вы должны распространять также и <<сырой>> файл PSD. Этот <<\textit{исходный код}>> вы должны или распространять сразу вместе с окончательным вариантом (PDF, печатной версией и т.п.), или в PDF или печатную версию должна быть включена информация о том, как получить этот <<\textit{исходный код}>>. Более строгие определения см. в полном тексте лицензии, ссылки на который приведены выше. 16 | 17 | \subsection*{Дополнительные замечания} 18 | \small 19 | 20 | Вообще, часто для подобных <<творческих работ>> используются лицензии Creative Commons (CC). Но я распространяю эти заметки на условиях именно GNU GPL потому, что CC-лицензии не содержат понятия исходного кода и не требуют его раскрытия. Если бы я распространял заметки на условиях лицензий CC, то кто угодно мог бы внести изменения в \LaTeX-исходники, скомпилировать их в PDF и дальше распространять только PDF, а \LaTeX-исходники засекретить. Это довольно непродуктивно, т.к. скомпилированный PDF править намного сложнее, чем \LaTeX-исходники. Я хочу, чтобы все измененные версии этих заметок сопровождались исходниками, чтобы их мог править кто угодно, да и чтобы я сам мог подходящие изменения включить в оригинальный текст заметок. Соответственно, GNU GPL имеет понятие \textit{исходного кода}, причем с достаточно широким определением: <> (<<предпочитаемая форма произведения для создания его модификаций>>). Для заметок, набранных в \LaTeX, исходный код "--- это очевидно исходный код \LaTeX, поэтому GPL позволяет достичь именно той цели, которую я сформулировал выше: она требует, чтобы всякий, кто будет распространять измененную версию заметок, распространял бы и соответствующий исходный код \LaTeX. 21 | 22 | Кстати, исходный код этих заметок лежит в репозитории на GitHub. Если уж вы изменяете заметки, я буду очень рад, если вы пришлете pull request, чтобы я мог при желании легко включить ваши изменения в мою версию. 23 | 24 | Еще обратите внимание, что лицензия, конечно, относится только к конкретному тексту этих заметок. Авторское право вообще защищает не идеи, а конкретные воплощения этих идей, поэтому, конечно, я не претендую и не могу претендовать на какие-либо авторские права в отношении алгоритмов, задач и т.п., описанных в этих текстах. Авторские права распространяются только на конкретную текстовую формулировку этих алгоритмов и задач. 25 | Кроме того, конечно, я разрешаю свободное использование без каких-либо требований лицензии разумно небольших фрагментов этих заметок. Например, вы, конечно, можете использовать фрагменты кода (но не целые программы), приведенные в этих заметках, в своих программах без каких-либо ссылок на меня, или формулировки отдельных задач и т.п. 26 | 27 | Раньше я распространял некоторые фрагменты этих заметок по лицензии CC-BY-SA. Конечно, на них по-прежнему распространяется эта лицензия, но на этот текст и на последующие версии распространяется только лицензия GPL. -------------------------------------------------------------------------------- /_all/problems.cls: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e} 2 | \ProvidesClass{problems}[2006/11/03] 3 | 4 | % identification 5 | % initial code 6 | % declaration of options 7 | % execution of options 8 | % package loading 9 | % main code 10 | 11 | % Declaration of Options 12 | \DeclareOption{draft}{\PassOptionsToClass{draft}{report}\AtEndOfClass{\geometry{showframe}}} 13 | \DeclareOption{10pt}{\PassOptionsToClass{10pt}{report}} 14 | \DeclareOption{11pt}{\PassOptionsToClass{11pt}{report}} 15 | \DeclareOption{12pt}{\PassOptionsToClass{12pt}{report}} 16 | 17 | \hfuzz=0.1cm 18 | 19 | % Опцию a4paper будем использовать для формата, в котором задачки 20 | % печатались раньше на бумаге A4. 21 | \DeclareOption{a4paper}{ 22 | \PassOptionsToPackage{a4paper,includehead,includefoot,headheight=10pt,headsep=2mm,width=17cm,height=27cm,footskip=0.5cm}{geometry} 23 | } 24 | 25 | % Execution of Options 26 | \ProcessOptions\relax 27 | 28 | \PassOptionsToClass{russian}{report} 29 | 30 | % Package Loading 31 | \LoadClass[a4paper]{report} 32 | 33 | \RequirePackage[T2A]{fontenc} 34 | \RequirePackage[utf8]{inputenc} 35 | \RequirePackage[russian]{babel} 36 | \RequirePackage{mathtext} 37 | \RequirePackage[dvipdfmx,final]{graphicx} 38 | \RequirePackage{wrapfig} 39 | \RequirePackage{amssymb} 40 | \RequirePackage{amsmath} 41 | \RequirePackage{amscd} 42 | \RequirePackage{array} 43 | \RequirePackage{multicol} 44 | \RequirePackage{longtable} 45 | \RequirePackage[dvips]{geometry} 46 | \RequirePackage{titlesec} 47 | \RequirePackage{fancyhdr} 48 | \RequirePackage{framed} 49 | \RequirePackage{verbatim} 50 | %\RequirePackage[dvipdfmx]{hyperref} 51 | 52 | % Main Code 53 | \columnseprule=0.4pt 54 | \raggedbottom 55 | 56 | % AK: думаю, лучше везде использовать вариант "". 57 | %\declare@shorthand{russian}{""}{\nobreak\hskip.2em\ignorespaces} 58 | %\declare@shorthand{russian}{",}{\nobreak\hskip.2em\ignorespaces} 59 | % KAP: чтобы кавычки всегда были правильные 60 | %\declare@shorthand{russian}{"<}{<<} 61 | %\declare@shorthand{russian}{">}{>>} 62 | %---------- From package "lastpage" ------------------ 63 | \def\lastpage@putlabel{\addtocounter{page}{-1}% 64 | \immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}% 65 | \addtocounter{page}{1}} 66 | \AtEndDocument{\clearpage\lastpage@putlabel}% 67 | %---------- end of "lastpage" ------------------ 68 | 69 | \titlelabel{\thetitle.\quad} 70 | \titleformat{\chapter}[display]{\Huge\sf\bfseries}{\chaptertitlename{} \thechapter.}{1em}{} 71 | \assignpagestyle{\chapter}{fancy} 72 | \addto\captionsrussian{% 73 | \def\chaptername{Часть}% 74 | \def\appendixname{Приложение}% 75 | } 76 | 77 | \titleformat{\section}{\normalfont\Large\sf\bfseries}{\thesection.}{1em}{} 78 | \newcommand{\headernono}[1]{% 79 | \section*{#1} 80 | } 81 | 82 | \newcommand{\header}[1]{% 83 | \section{#1} 84 | } 85 | 86 | \titleformat{\subsection}[hang]{\normalfont\normalsize\sf\bfseries}{\thesubsection.}{1em}{} 87 | \titlespacing{\subsection}{0em}{0.5em}{0em} 88 | \newcommand{\lheadernd}[1]{% 89 | \subsection{#1}% 90 | } 91 | \newcommand{\lheader}[1]{% 92 | \subsection{#1}% 93 | } 94 | 95 | \newcommand\Headerproper[1]{ 96 | \chapter{#1} 97 | } 98 | 99 | \newcommand{\Headern}[1]{% 100 | \endgroup 101 | \immediate\openout\dup=\jobname.dup\relax% 102 | \immediate\write\dup{#1}% 103 | \immediate\closeout\dup% 104 | \newread\dupread 105 | \openin\dupread=\jobname.dup\relax 106 | \read\dupread to\fileline 107 | \closein\dupread 108 | \Headerproper{\fileline}% 109 | \immediate\write\tsk{\noexpand\lheader{#1}} 110 | \immediate\write\hnt{\noexpand\lheader{#1}} 111 | \immediate\write\ans{\noexpand\lheader{#1}} 112 | } 113 | 114 | \newcommand{\Header}{% 115 | \begingroup\makerusother\Headern 116 | } 117 | 118 | \setcounter{secnumdepth}{3} 119 | \titleformat{\subsubsection}[runin]{\normalfont\normalsize\bfseries}{\thesubsubsection.}{1em}{} 120 | \newcommand{\llheader}{% 121 | \subsubsection{} 122 | } 123 | 124 | %\def\nought{\ensuremath{{\mkern-3.25mu{\not}\mkern3.25mu\mbox{\tt0}}}} 125 | \def\slnought{{\tt\O}} 126 | 127 | \newcommand{\todo}[1]{\marginpar{\raggedright\footnotesize!~TODO:\\#1}} 128 | 129 | \pagestyle{fancy} 130 | \fancyhf{} 131 | \renewcommand{\headrulewidth}{0pt} 132 | \renewcommand{\footrulewidth}{0pt} 133 | 134 | \cfoot{% 135 | \vbox{% 136 | \hrule\vspace{0.1cm}% 137 | \hbox to \textwidth{% 138 | \sf\footnotesize% 139 | \hfill\strut Страница \thepage\ из \pageref{LastPage}\hfill% 140 | }}} 141 | 142 | \renewcommand{\leq}{\leqslant} 143 | \renewcommand{\le}{\leqslant} 144 | \renewcommand{\geq}{\geqslant} 145 | 146 | \newcommand{\unit}[1]{\mbox{ \rm #1}} 147 | % \vstring#1 148 | % Написать #1 как строку вх/вых файла (в кавычках шрифтом \tt без 149 | % переносов) 150 | \newcommand*{\vstring}[1]{`\mbox{\tt#1}'} 151 | 152 | %БАГ: пока не работает генерация автоматических ссылок на пункты перечня 153 | \newcounter{tmp} 154 | 155 | \newenvironment{ulists}[2]{% 156 | \begin{list}{#1}{\topsep=0.6ex plus 0.3ex minus 0.6ex \partopsep=0.6ex minus 0.6ex \parsep=0pt \itemsep=0pt #2}% 157 | } 158 | {\end{list}} 159 | 160 | \newenvironment{ulist}{% 161 | \begin{ulists}{$\bullet$}{}% 162 | } 163 | {\end{ulists}} 164 | 165 | \newenvironment{olist}{% 166 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 167 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{}% 168 | } 169 | {\end{ulists}} 170 | 171 | \newenvironment{olistzero}{% 172 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 173 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \partopsep=0ex}% 174 | } 175 | {\end{ulists}} 176 | 177 | \newenvironment{wideolist}{% 178 | \setcounter{tmp}{0}\renewcommand{\thetmp}{\arabic{tmp}} 179 | \begin{ulists}{\refstepcounter{tmp}\thetmp.}{\topsep=0ex \parsep=0pt \itemsep=0pt \leftmargin=0pt \itemindent=\labelwidth}% 180 | } 181 | {\end{ulists}} 182 | 183 | % Нумерованный список с сквозной нумерацией 184 | \newcounter{olistcount}\renewcommand{\theolistcount}{\arabic{olistcount}} 185 | \newcommand{\resetolist}{\setcounter{olistcount}{0}} 186 | \newenvironment{olistc}{% 187 | \renewcommand{\theolistcount}{\arabic{olistcount}} 188 | \begin{ulists}{\refstepcounter{olistcount}\theolistcount.}{}% 189 | } 190 | {\end{ulists}} 191 | 192 | % Нумерованный список для использования в тексте, когда каждый пункт 193 | % пишется с маленькой буквы и отделяется ";". 194 | % Здесь помечается арабской цифрой со скобкой. 195 | \newenvironment{tllist}{% 196 | \setcounter{tmp}{0} 197 | \begin{ulists}{\refstepcounter{tmp}\thetmp)}{}% 198 | } 199 | {\end{ulists}} 200 | 201 | \newcommand*{\hm}[1]{#1\nobreak\discretionary{}{\hbox{$\mathsurround=0pt #1$}}{}} 202 | 203 | \newcommand{\wvec}[1]{\overrightarrow{#1}} 204 | 205 | \newcommand{\wnote}[1]{{\sl [~#1~]\todo{!}}} 206 | 207 | \relpenalty=10000 208 | \binoppenalty=10000 209 | 210 | \newcommand{\OR}{\mathrel{\mathrm{or}}} 211 | \newcommand{\XOR}{\mathrel{\mathrm{xor}}} 212 | \newcommand{\AND}{\mathrel{\mathrm{and}}} 213 | \newcommand{\NOT}{\mathop{\mathrm{not}}} 214 | \newcommand{\SHL}{\mathop{\mathrm{shl}}} 215 | \newcommand{\SHR}{\mathop{\mathrm{shr}}} 216 | 217 | 218 | % Суммарная ширина столбцов в двухколоночной таблице, выровненной по ширине 219 | \newlength\twowidth 220 | \newcommand{\settwowidth}{ 221 | \twowidth=\textwidth 222 | \addtolength\twowidth{-4\tabcolsep} 223 | \addtolength\twowidth{-3\arrayrulewidth} 224 | } 225 | \AtBeginDocument{\settwowidth}%т.к. \textwidth надо сначала установить 226 | 227 | % --= поддержка примеров программ, сделаных conv.pas =-- 228 | % Это для борьбы с разрывами страницы после окружений multicols 229 | \newlength{\cs@topskip} 230 | \newlength{\cs@bottom} 231 | \newlength{\cs@bottomback} 232 | \newlength{\cs@top} 233 | \cs@topskip=1.5ex 234 | \cs@bottom=1.5ex 235 | \cs@bottomback=1ex plus 0.5ex minus 0.3ex 236 | \footnotesize\cs@top=2.4ex\normalsize 237 | 238 | \newenvironment{codesamplec}[1] 239 | {% локальные определения: 240 | \newcommand{\codelf}{\kern-1.5em\\}% 241 | \newcommand{\codespace}{{\ttfamily\symbol{`\ }}}% 242 | \newcommand{\codetok}[1]{{\bfseries##1}}% 243 | \newcommand{\codecmt}[1]{{\ttfamily\slshape##1}}% 244 | \vspace{0.5ex plus 0.3ex minus 0.1ex} 245 | \topskip=\cs@topskip%KAP: не знаю почему, но работает :):):) !!! От этого параметра зависимость --- пороговая. Пришлось еще подрегулировать \vspace строкой ниже 246 | %KAP: тут где-то еще видимо затесался vspace с plus/minus компонентой, так что, если сильно ужимать страницу, то все переедет... 247 | \par\begin{multicols}{#1}[\footnotesize\hrule\nopagebreak\vspace{-\cs@top}]\tt\noindent} 248 | {\end{multicols}\par\vspace*{-\cs@bottom}\hrule\vspace*{\cs@bottomback}\pagebreak[0]} 249 | 250 | \newenvironment{codesample}{\begin{codesamplec}{2}}{\end{codesamplec}} 251 | 252 | \newenvironment{codesampleo} 253 | {\vspace{0.5ex plus 0.3ex minus 0.1ex} 254 | \par\footnotesize\hrule\nopagebreak\vspace{-1.3ex}\tt\noindent} 255 | {\par\nopagebreak\vspace{-1.3ex}\hrule\vspace{\cs@bottomback}} 256 | 257 | % --= * =-- 258 | 259 | \newcommand{\noten}[2]{{\vspace{0.1cm}\par\pagebreak[3]\small \textit{#1:} #2 \vspace{0.1cm plus 0.1cm}\par}} 260 | \newcommand{\note}[1]{\noten{Примечание}{#1}} 261 | 262 | \newcommand{\eps}{\varepsilon} 263 | 264 | \newcommand{\epigraph}[2]{%\hangindent=0.4\textwidth\begin{flushright}\small\textit{#1}\par\footnotesize#2\par\end{flushright} 265 | {\parindent=0cm 266 | \parshape 1 0.4\textwidth 0.6\textwidth 267 | \begin{flushright}% 268 | \small\textit{#1}\par% 269 | \vspace{0.1cm}% 270 | \footnotesize#2\par% 271 | \end{flushright}}% 272 | } 273 | 274 | \newcounter{taskcount}[chapter] 275 | \renewcommand{\thetaskcount}{\arabic{chapter}.\arabic{taskcount}} 276 | \newcommand{\taskon}[2]{% 277 | \refstepcounter{taskcount}% 278 | \textbf{#1\mbox{~}\thetaskcount:} {\it #2}% 279 | } 280 | \newcommand{\tasko}[1]{\taskon{Задание}{#1}} 281 | 282 | \newcommand{\hint}[2]{\textbf{Посказка \ref{#1}:} #2} 283 | 284 | \newcommand{\answer}[2]{\textbf{Ответ \ref{#1}:} #2} 285 | 286 | \renewcommand{\ddots}{\,\,.\,.\,\,} 287 | 288 | %ANSWERS + 289 | \newlinechar=`\^^M 290 | 291 | \newwrite\tsk 292 | \immediate\openout\tsk=\jobname.tsk\relax 293 | \newwrite\ans 294 | \immediate\openout\ans=\jobname.ans\relax 295 | \newwrite\hnt 296 | \immediate\openout\hnt=\jobname.hnt\relax 297 | \newwrite\dup 298 | 299 | \def\makerusother{% 300 | \@tempcnta128\relax% 301 | \loop% 302 | \catcode\@tempcnta12% 303 | \ifnum\@tempcnta<255\relax% 304 | \advance\@tempcnta\@ne% 305 | \repeat% 306 | } 307 | 308 | \def\makeallother{% 309 | \let\do\@makeother\dospecials% 310 | \makerusother% 311 | } 312 | 313 | \def\writeansno#1#2{% 314 | \begingroup% 315 | \makeallother% 316 | \obeylines% 317 | \long\def\copyans#2##1#2{% 318 | \def\tmp{##1}% 319 | \if\tmp\empty% 320 | \else% 321 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 322 | \immediate\write#1{##1}% 323 | \fi% 324 | \endgroup\afterwriteans% 325 | }% 326 | \copyans#2% 327 | } 328 | 329 | \def\dupeans#1#2{% 330 | \immediate\write#1{\noexpand\answer{\taskname{} \thetaskcount}{\thepage}}% 331 | \immediate\openout\dup=\jobname.dup\relax% 332 | \begingroup% 333 | \makeallother% 334 | \obeylines% 335 | \long\def\copyans#2##1#2{% 336 | \immediate\write#1{##1}% 337 | \immediate\write\dup{##1\noexpand\endinput}% 338 | \endgroup\immediate\closeout\dup% 339 | \input{\jobname.dup}% 340 | \afterwriteans% 341 | }% 342 | \copyans#2% 343 | } 344 | 345 | \def\tasknn#1{% 346 | \endgroup% 347 | \refstepcounter{taskcount}% 348 | \gdef\taskname{#1}% 349 | \immediate\openout\dup=\jobname.dup\relax% 350 | \immediate\write\dup{\noexpand\taskcaption{\taskname{}\noexpand~\thetaskcount:}\noexpand\endinput}% 351 | \immediate\closeout\dup% 352 | \input{\jobname.dup}% 353 | \let\afterwriteans\relax% 354 | \gdef\afterwriteans{% 355 | \gdef\afterwriteans{% 356 | \let\afterwriteans\endgroup% 357 | \writeansno\ans% 358 | }% 359 | \writeansno\hnt% 360 | } 361 | \begingroup\it% 362 | \dupeans\tsk% 363 | } 364 | 365 | \def\taskn{% 366 | \begingroup\makerusother\tasknn% 367 | } 368 | 369 | {\makerusother 370 | \gdef\deftaskname{Задание} 371 | } 372 | 373 | \def\task{\taskn{\deftaskname}} 374 | 375 | \def\taskcaption#1{\textbf{#1}} 376 | 377 | \long\def\answer#1#2{ 378 | \par\pagebreak[3]\mbox{\taskcaption{#1} (стр. #2):} 379 | } 380 | 381 | \def\inputanswers{% 382 | \immediate\closeout\tsk 383 | \immediate\closeout\hnt 384 | \immediate\closeout\ans 385 | \appendix 386 | \Headerproper{Задачи и ответы} 387 | \header{Условия всех задач} 388 | \input{\jobname.tsk} 389 | \eject\header{Подсказки} 390 | \input{\jobname.hnt} 391 | \eject\header{Ответы} 392 | \input{\jobname.ans} 393 | } 394 | 395 | -------------------------------------------------------------------------------- /conv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | dos2unix $1 3 | iconv -f cp866 -t utf8 <$1 >$1.utf8 4 | mv $1.utf8 $1 -------------------------------------------------------------------------------- /icheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | FROM_ENCODING=utf-8 3 | ISPELL_ENCODING=cp866 4 | iconv -f $FROM_ENCODING -t $ISPELL_ENCODING <$1 >$1.$ISPELL_ENCODING 5 | ispell $1.$ISPELL_ENCODING 6 | iconv -f $ISPELL_ENCODING -t $FROM_ENCODING <$1.$ISPELL_ENCODING >$1 7 | rm $1.$ISPELL_ENCODING 8 | -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petr-kalinin/progtexts/61ff767758150c283a08afdc08f70a0ddae38ba2/todo.txt --------------------------------------------------------------------------------