-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.json
1 lines (1 loc) · 459 KB
/
search.json
1
[{"title":"equation test","url":"/2022/02/18/equation_test/","content":"\nYour browser does not support the video tag.\nThis is my website, click the button ButterflyThis is my website, click the button Butterfly\n默认 提示块标籤\n\ndefault 提示块标籤\n\nprimary 提示块标籤\n\nsuccess 提示块标籤\n\ninfo 提示块标籤\n\nwarning 提示块标籤\n\ndanger 提示块标籤\n\n\n 纯文本测试\n \n\n 支持简单的 markdown 语法\n \n\n 支持自定义颜色\n \n\n 绿色\n \n\n 黄色\n \n\n 青色\n \n\n 蓝色\n ","tags":["acwing"]},{"title":"Markdown语法显示效果","url":"/2022/02/22/markdown%E8%AF%AD%E6%B3%95%E6%98%BE%E7%A4%BA%E6%95%88%E6%9E%9C/","content":"h1h2h3h4h5h6\n这段文字将会被高亮显示\n\n\n无序列表1 \n无序列表2\n无序列表3\n\n\n有序列表1\n有序列表2\n有序列表3\n\n\n\n\n动物\n\n水生动物陆生动物\n\n猴子人\n\n程序猿攻城狮产品狗射鸡虱\n\n\n两栖类动物\n\n大鳄鱼唐老鸭\n\n\n\nxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n作者出处\nxxxxxxxxxxxxxxxxxxxxxxxxxx\n@作者 网络地址\n臣亮言:先帝 創業未半,而中道崩殂 。今天下三分,益州疲敝 ,此誠危急存亡之秋 也!然侍衞之臣,不懈於內;忠志之士 ,忘身於外者,蓋追先帝之殊遇,欲報之於陛下也。誠宜開張聖聽,以光先帝遺德,恢弘志士之氣;不宜妄自菲薄,引喻失義,以塞忠諫之路也。宮中、府中,俱為一體;陟罰臧否,不宜異同。若有作奸 、犯科 ,及為忠善者,宜付有司,論其刑賞,以昭陛下平明之治;不宜偏私,使內外異法也。\n\n[ ] content \n[x] content\n\n这里是斜体这里是斜体\n这里是加粗这里是加粗\n这里是加粗并斜体这里是加粗并斜体\n\n\n\n\n左对齐\n右对齐\n居中\n\n\n\n\nComputer\n5000 元\n1台\n\n\nPhone\n1999 元\n1部\n\n\n\n\nC++Python# include <iostream>a = input()\n内容[1]\n[1] 说明\n默认 提示块标签\n\ndefault 提示块标签\n\nprimary 提示块标签\n\nsuccess 提示块标签\n\ninfo 提示块标签\n\nwarning 提示块标签\n\ndanger 提示块标签\n\n","tags":["Markdown"]},{"title":"Hexo在线预览PDF","url":"/2022/03/14/ttpdf/","content":"本文介绍两种在Hexo中在线预览PDF的方法\n基于hexo-pdf\n安装$ npm install --save hexo-pdf\n使用{% pdf https://repo.holgerbest.top/pdf/default.pdf %}\n效果\n\n\t\n \n\t\n\n\n\n\n\n基于Htmlobject\n使用\n<object data="https://repo.holgerbest.top/pdf/default.pdf" type="application/pdf" width="100%" height="800px">\n\n效果\n\n\n\n\n\niframe\n使用\n\n<iframe src="https://repo.holgerbest.top/pdf/default.pdf" width="100%" height="800px" frameborder="0" scrolling="yes"></iframe>\n\n效果\n\n\n\n","categories":["干货"],"tags":["干货"]},{"title":"关于在C++中字符串的输入整理笔记","url":"/2022/02/26/algorithm/c++%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%AF%BB%E5%85%A5%E6%80%BB%E7%BB%93/","content":"\n转载:https://www.acwing.com/blog/content/12066/\n\n1. cincin是C++中最常用的输入语句,当遇到空格或者回车键即停止\n如:#include <iostream>#include <string>using namespace std;int main(){ char a[50]; cin>>a; cout<<a<<endl; return 0;}输入:abcd遇回车输出abcd\n缺点:只能输入没有空格的字符串,当输入中含有空格,则只能输出空格之前的字符\n输入:I love China输入空格时输入并未停止,遇回车输入停止,输出I,空格后面的均未输出。\n2. gets()可以无限读取,以回车结束读取,C语言中的函数。\n如:#include <iostream>#include <cstdio>using namespace std;int main(){ char a[50]; gets(a); cout<<a<<endl; return 0;}输入:I love China回车结束输入,输出结果为I love China。\n3. getline()若定义变量为string类型,则要考虑getline()函数。用法如下:#include <iostream>#include <string>using namespace std;int main(){ string a; getline(cin,a); cout<<a<<endl; return 0;}输入:I love China回车并未结束输入,需回车两次才能结束输入,输出结果为:I love China.\n4.cin.get cin.getlinecin.get()函数可以接收空格,遇回车结束输入。#include <iostream>using namespace std;int main(){ char a[50]; cin.get(a,50); cout<<a<<endl; return 0;}输入:I love China回车结束输入,输出结果为I love China。\n5. cin.getlinecin.getline()函数可以同cin.get()函数类似,也可接收空格,遇回车结束输入。\n#include <iostream>using namespace std;int main(){ char a[50]; cin.getline(a,50); cout<<a<<endl; return 0;}\n输入:I love China回车结束输入,输出结果为I love China。\n","categories":["算法与数据结构"],"tags":["C++"]},{"title":"Paper Reading - [NIPS 2012] ImageNet Classification with Deep Convolutional Neural Networks","url":"/2022/03/11/paper_reading/alexnet/","content":"前言AlexNet作为深度学习er必经之路上必须学习的网络结构,在现在来看其网络结构可能“过于简单”。但是作为深度学习的开山之作,我们还是要仔细学习作者的思想,包括对当前问题的分析、实验思路等。这里我们就对论文进行简单总结,详细的论文解读可以参考b站这里的视频哦。\nAbstract\n训练了一个深度卷积网络,拿下了2010年ImageNet图片分类的冠军(事实证明,拿了冠军论文写的很烂也可以中顶会)。top-1 error 37.5%, top-5 error 17.0%\n2021年ImageNet亚军 top-1 error 26.2%, top-5 error 15.3%\n\nIntroduction\n提高分类性能需要大量数据集。\nCNN虽然参数相对较少,在大量数据集的前提下性能可能稍微差一点。\nGPU可以加速训练\n\n本文贡献:\n\n训练了一个巨牛逼的网络,在2010和2012 ImageNet图片分类比赛上效果都很好\n一个高度优化的2D卷积的GPU实现\n一些防止过拟合的策略\n卷积 + 全连接的搭配似乎很神奇\n\nThe Dataset介绍ImageNet 2010。\n由于图片分辨率太大,作者将输入图片降采样至256 x 256,即中心裁剪。然后减去均值,作为训练集。\nThe Architecture这部分介绍了模型的整体架构,以下介绍的顺序是作者认为相对重要的。\nReLU Nonlinearity作者使用的激活函数为Relu。在CIFAR-10数据集的实验表明,使用Relu网络训练更快。\nTraining on Multiple GPUs这部分其实没什么好讲的,作者似乎花了大功夫实现了分布式训练。\nLocal Response Normalization看到过很多次了,现在好像很少使用了。详解回头补充吧。。。\nOverlapping Pooling传统方式的池化都是不带有重叠的,作者发现带有重叠的池化似乎更加不容易过拟合。\nOverall Architecture\n详细的参数还是看源码比较清楚, 注意网络的输入为224 x 224 x 3\nnet = nn.Sequential(\tnn.Conv2d(in_channels=1, out_channels=96, kernel_size=11, stride=4, padding=1), nn.ReLU(),\tnn.MaxPool2d(kernel_size=3, stride=2),\tnn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, padding=2), nn.ReLU(),\tnn.MaxPool2d(kernel_size=3, stride=2),\tnn.Conv2d(in_channels=256, out_channels=384, kernel_size=3, padding=1), nn.ReLU(),\tnn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, padding=1), nn.ReLU(),\tnn.Conv2d(in_channels=384, out_channels=256, kernel_size=3, padding=1), nn.ReLU(),\tnn.MaxPool2d(kernel_size=3, stride=2),\tnn.Flatten(),\tnn.Linear(6400, 4096),\tnn.Dropout(0.5),\tnn.Linear(4096, 4096),\tnn.Dropout(0.5),\tnn.Linear(4096, 1000))\nReducing OverfittingAlexNet 大约有6千万参数,目前使用的数据集也很难去训练这些参数,很容易过拟合。这部分讲作者为了减少过拟合使用了哪些方法。\nData Augmentation非常实用的方法,作者实现了两个数据增强的方法。\n\nrandom crop\n\n在训练时,作者从256x256随机裁剪出224x224,包括水平和垂直翻转图片。这使得训练集大约扩增了2048倍。\n在测试时,作者从四个角+中心随机裁剪出224x224,包括水平和垂直翻转,然后对softmax的结果取平均选最大作为最终结果。\n\naltering the intensities of the RGB channels \n\n换句话说,就是改变三通道RGB值的强度。作者认为,自然图片的一大特性是,即使改变光强和颜色物体仍会保持其不变性。作者采用的一种方式是,首先对整个训练集的图片每个通道、每个pixel做PCA降维。选出最重要的三个特征值及其对应的特征向量。在训练时,对于每张图片三通道的每个像素I_{xy} = [I_{xy}^R,I_{xy}^G,I_{xy}^B],加上一个值\n\n[p_1, p_2, p_3][\\alpha_1\\lambda_1, \\alpha_2\\lambda_2, \\alpha_3\\lambda_3]^T其中服从均值为0标准差为0.1的高斯分布\nDropout随机丢弃,无须多言\nDetails of learning\nbatch size = 128\nSGD \nweight decay = 0.0005, momentum = 0.9\n参数初始化,卷积层Norm(0, 0.01)\n2、4、5 + 全连接层的bias初始化为1;其余层bias初始化为0\n学习率初始化为0.01,验证集误差不减小时学习率减少10倍\n\nResultsILSVRC-2010\n\nILSVRC-2012\n\nQualitative Evaluations量化评估\nDIscussion\n深度卷积网络很强\n移除alexnet 网络的任意一层都会导致性能的下降\n没有使用无监督预训练\n未来想用在视频序列上,因为更有时序性\n\n竟然没有结论这篇论文\n","categories":["Paper Reading"],"tags":["AlexNet","NIPS","CV"]},{"title":"Paper Reading - [CVPR 2015] Going deeper with convolutions","url":"/2022/03/11/paper_reading/googlenet/","content":"","categories":["Paper Reading"],"tags":["CV","GoogLeNet","CVPR"]},{"title":"Paper Reading - [CVPR 2016] Rethinking the Inception Architecture for Computer Vision","url":"/2022/03/11/paper_reading/inception_v3/","content":"前言Abstract","categories":["Paper Reading"],"tags":["CV","CVPR","Inception-v3"]},{"title":"Paper Reading - [CoRR 2015] Very Deep Convolutional Networks for Large-Scale Image Recognition","url":"/2022/03/11/paper_reading/vgg/","content":"","categories":["Paper Reading"],"tags":["CV","VggNet","CoRR"]},{"title":"pyTorch获取中间层输出的几种方法","url":"/2021/07/18/python/Pytorch%E8%8E%B7%E5%8F%96%E4%B8%AD%E9%97%B4%E5%B1%82%E8%BE%93%E5%87%BA%E7%9A%84%E5%87%A0%E7%A7%8D%E6%96%B9%E6%B3%95/","content":"总结了3种输出网络中间层的方法\n\n方法1import torchimport torch.nn as nnmodel = nn.Sequential( nn.Conv2d(3, 9, 1, 1, 0, bias=False), nn.BatchNorm2d(9), nn.ReLU(inplace=True), nn.AdaptiveAvgPool2d((1, 1)), )# 假如想要获得ReLu的输出x = torch.rand([2, 3, 224, 224])for i in range(len(model)): x = model[i](x) if i == 2: ReLu_out = xprint('ReLu_out.shape:\\n\\t',ReLu_out.shape)print('x.shape:\\n\\t',x.shape)\n方法2from collections import OrderedDict import torchfrom torch import nn class IntermediateLayerGetter(nn.ModuleDict): """ Module wrapper that returns intermediate layers from a model It has a strong assumption that the modules have been registered into the model in the same order as they are used. This means that one should **not** reuse the same nn.Module twice in the forward if you want this to work. Additionally, it is only able to query submodules that are directly assigned to the model. So if `model` is passed, `model.feature1` can be returned, but not `model.feature1.layer2`. Arguments: model (nn.Module): model on which we will extract the features return_layers (Dict[name, new_name]): a dict containing the names of the modules for which the activations will be returned as the key of the dict, and the value of the dict is the name of the returned activation (which the user can specify). """ def __init__(self, model, return_layers): if not set(return_layers).issubset([name for name, _ in model.named_children()]): raise ValueError("return_layers are not present in model") orig_return_layers = return_layers return_layers = {k: v for k, v in return_layers.items()} layers = OrderedDict() for name, module in model.named_children(): layers[name] = module if name in return_layers: del return_layers[name] if not return_layers: break super(IntermediateLayerGetter, self).__init__(layers) self.return_layers = orig_return_layers def forward(self, x): out = OrderedDict() for name, module in self.named_children(): x = module(x) if name in self.return_layers: out_name = self.return_layers[name] out[out_name] = x return out# examplem = torchvision.models.resnet18(pretrained=True)# extract layer1 and layer3, giving as names `feat1` and feat2`new_m = torchvision.models._utils.IntermediateLayerGetter(m,{'layer1': 'feat1', 'layer3': 'feat2'})out = new_m(torch.rand(1, 3, 224, 224))print([(k, v.shape) for k, v in out.items()])# [('feat1', torch.Size([1, 64, 56, 56])), ('feat2', torch.Size([1, 256, 14, 14]))]\n方法3:hookclass TestForHook(nn.Module): def __init__(self): super().__init__() self.linear_1 = nn.Linear(in_features=2, out_features=2) self.linear_2 = nn.Linear(in_features=2, out_features=1) self.relu = nn.ReLU() self.relu6 = nn.ReLU6() self.initialize() def forward(self, x): linear_1 = self.linear_1(x) linear_2 = self.linear_2(linear_1) relu = self.relu(linear_2) relu_6 = self.relu6(relu) layers_in = (x, linear_1, linear_2) layers_out = (linear_1, linear_2, relu) return relu_6, layers_in, layers_outfeatures_in_hook = []features_out_hook = []def hook(module, fea_in, fea_out): features_in_hook.append(fea_in) features_out_hook.append(fea_out) return Nonenet = TestForHook()"""# 第一种写法,按照类型勾,但如果有重复类型的layer比较复杂net_chilren = net.children()for child in net_chilren: if not isinstance(child, nn.ReLU6): child.register_forward_hook(hook=hook)""""""推荐下面我改的这种写法,因为我自己的网络中,在Sequential中有很多层,这种方式可以直接先print(net)一下,找出自己所需要那个layer的名称,按名称勾出来"""layer_name = 'relu_6'for (name, module) in net.named_modules(): if name == layer_name: module.register_forward_hook(hook=hook)print(features_in_hook) # 勾的是指定层的输入print(features_out_hook) # 勾的是指定层的输出\n","categories":["教程"],"tags":["pyTorch"]},{"title":"2021年上海交通大学生物医学工程学院数字图像笔试题(全网最全)","url":"/2022/03/12/tutorials/2021%E5%B9%B4%E4%B8%8A%E6%B5%B7%E4%BA%A4%E9%80%9A%E5%A4%A7%E5%AD%A6%E7%94%9F%E5%8C%BB%E5%B7%A5%E6%95%B0%E5%AD%97%E5%9B%BE%E5%83%8F%E7%AC%94%E8%AF%95%E9%A2%98/","content":"\n 659a80ed77b9a3ecda24c3b995dd933d08c87e73ca1ed14a5be8aad47aff8da1920e043c537abdbd915176645fc05d2028fbd3ee17631458397d4087260f1f011fdd3cd871a84a41529f4878d7b262531a54bb3f624dd3c32b23b66c2eef34545dc3fb3fb545c12ad1c7209608701878e779bf5080c5b20f2fc717dbe48cb4aad036de924903ddc356525eeffb9ba86a4b6b761735266aa4f7da028ee7665f36bbd73e6253e89fb7ba7d31e66005c9bd06b63c17639bab10103b9d1447ed1fc1634647c2e71e55dc29e02d593d0cb6783620189af2638c0ef041775a22185b59f29a1d592f930b4b005ccd6cb724b0c440824f5065e8d5c22c853fe653cb70acde666266b9e4501fc9aad853584be0e09b585e1ef557d9397f4b5a7dffa557abf201dbf8bc458d4999751b5fdf0399b7c89f171c183708d41b7c15b929f3516886d3a32157cab2148ba9f46197d4dd5adcecea8c058dea8f9b2145fc06297dc9477dc825595c4151d27c3f3697a45ae63e789ec09fe7ae629117615762062c9c4d1de4569105647c8b343234acf4668105d441fa6f0ed2b2aaaca27aa85890ceb5a8c1ab75332bc495bd3eba57dc8ec8ebe941107e2311ac47d17684c580277dc97d9a06fc40c9c59151633654998574ec29cdefeb4e3f99ba6d728eea5926a514c68e900da35ea3b57a7bd8c7f95031f96c1e1f4b1a7b9ef8757af36a353ab64c50530b0b7865806da25f9b44b8b489b42bf1ad907b396d0ad70ca8eb53eddeae5f3657f706f350cc40923b162ea001c52e9df8892250bb1dcec8e5ca7f58d4c67ff48c462ada54c7e8c0d62a3dffde\n \n \n \n \n 您好, 这里需要密码.\n \n \n \n \n \n \n \n\n","categories":["干货"],"tags":["干货"]},{"title":"A request for code of paper","url":"/2022/03/09/tutorials/ask-for-code-email/","content":"Dear prof xxx\n Sorry to bother you. I am a student from Beihang University in China.\n My research is focused on diffuse optical tomography in deep learning. I have recently read your paper “Deep Learning Diffuse Optical Tomography“, which published in IEEE Transactions on Medical Imaging, Vol.39, No. 4, April 2020. I am very interseted in this artical and have studied it carefully. I try to validate your simulation, but I have some errors when using toast++ and Nirfast matlab toolbox to generate simulation data. If possible, could you please give me the source code of your paper. \nI”ve found the webpage http://bispl.weebly.com and your github repositpry, but I didn’t find the code related to this paper. So I will appreciate it very much if you give me your code. I promise they will be used only for research purposes.\nThank you very much!\nBest regards\n xx xx\n","categories":["干货"],"tags":["干货"]},{"title":"English Interview","url":"/2021/04/30/tutorials/%E8%8B%B1%E8%AF%AD%E9%9D%A2%E8%AF%95%E9%AB%98%E9%A2%91%E9%97%AE%E9%A2%98/","content":"\n fdce470aa48e507ad61ad4892d2912452abbc4c68792d922f0f76e59c9d0840686dceffd1dabec383d0d95fb7fe6dcd72d34becd6212faf66f2b7d055e48652e115dcfc261fd144f4b7a9ff38c681c97efa839fcfcfa89f4699c83f46bd406a1a309eabbc1cdfd65cf2ad1e3ebc7764f7bd2e7b79af4b9982f5dfa46ccbc4110db1421f53a95d06be71e626c07a2328effccb331a58283ee0d9a98bc8d9f524b19334178ac17fcd057e99a0e95d8f7a7554050bbaa156e649624391ae0045c42f63bc18ad500a91980c6267634bdea12788c55f05f3cfed24ea9f1546b4c8b1ab1b78d27c283be017c6317bad262b87bd6658a7c1d2b61e5c6a740ffc502df99b171c43cfdb39baa7c9131fe2e07093c9becc5170bb6033f16dad318714459867a642e6f73652d792d8cb8f1531efb2e9dfd9fb5e5cf70ab3c362139aa4361f0089ec208fe395142d91db43e632d104211c0b053586799e09554fd04d52d34eee30c0ebc7c8a43f34005aebe92d073ffad46a4be029cb43d5908f54b818ec3791bad8649407c61f3d27353b28884af2a4b356995ceaf11358f258a79cf285689199fa371c1c16faa7bdf92a8f6bc8ef560be1d1e46d2cea8293b171bc082361da7047db1eb79f7d43e0cc4ac5ddb0b1655446a78a3881eb15e669498314eadc72ed62e9107b7e57066eea1e27d0c5e8256a930b0142466ec9646e49bcbd1755bbe9530e22b1e604b186f0cab28683ee0aa0df0ee2a704dd2704384b58f39508b441fe6e5866a196605e4b9f8ca86668da1e481c209d3c05a3848eb3113e9403ecbaf8d9dcf354c3de2024f4f2bcd1c68ad05098c80f84819968d922618030ddbef2b87a73c539147e6ef75160302e6d22f29948907d37d628f153dd6b307973b825aa0a7be918ad3df7ac59a304b72d8d47c97288b244462a1abdd1e1f218fd41e4ba9c3213ca2477bf37db6db236735122632010cd860d44e17bba6721cedb7f1bd1c2f3f68627e3448c58c253ac1b4c32ae10f03f5a94643f30830b3979bb8b09a0e7748200181ce68787456bacd09bb07bc6c4a5fa64d26ace43a2cc8be671f69fbeba1d0443e2d85faf2ae22e65297e72795165d9fcc3f58e81755effacebbbf1580d255810331c44a272f0bc7334b7ff50c8215d86747cd1121ed778b4606e7874c5cc906db5db9149552ae521e98239c812af99e709fcf483bf60385110b8b3b91ab86638cdd1e23a92a14db0fb546494de0b042ac616f7f571212c6deeaab6487b62a154ac886f716ee58a041cd0e2e2403f3fdca8312fdf0df859f7cf8929f16e0fa3a91cf9594ca7e2dc61b284dd7e096ea5cfe8cd7423cdad7e863add6fae98fbea620715c59af5744ada460ec2564ebe23319720423a881a592e83e8a3d9d2295d4417221cf28c2cdc7b5b4dad15cc2e150910bf4e0096eacfa180e8d3433078fbb9b59cf15bd7aaeedcc23e665c7f7c4b14b21190e86deec95fbb406939124946374e9c8800087f080adb4f990be6d72a0859dee3e725006642698012756c66f44235bd9d1414e51c6fdfd65cac57a72f0031784428e31e5841ea6d7ef799a5f4d64065af22a2e8d9bec5051f66ca7dd5da5740edf149f4eab32c696c86bad87a5f426ce00b0909366e41e8adc0591325dff119b7b034a11c3b261ff24168f391f76f4a0071ae097094f760d4d6b969919830fd04efeef5a6487a56895d56429120d0aef166983dbaaff16da37854b7693e8bbf4cafe53016eeb051a011782054ba2872edd3ab42b40b2ff72eb264f4bffffe9297ec0213de491616582e869694e429c8e47875f02a3c877e3236db1fa19585c22b46ada05e8607cc35c679b624a0233d4f73bef6435e74a0a5d5e46a36f0e3b1517f1d7d8de66e2ef2d0b7dc8ef158216e68adbf12a616550ffcadda2ae16b4afa7da8c511b58a777ebccc37bafbdb442d6e3af446df5148bc731f7e13caf77d2e3800f49c5b40df78a2f1892416004067f1f7253321aef0159575cd02b1bc5526b2f2eabc7edb4f7545aee057beb8d5c0669adf1ac63c259c47b85313b870fdb60e784aaab49f1b9ea1045030033484e1acf0243813ff9008be83336b2fb13400814d513563c525c2b8644ba9520c85531a829128f74aba603050a9f136b9f2db0e16a9cd79e9c6df93893870eac66034af734d7cf2208c0a296da28744dd13715ce8d78f8563f49b68dfb488eb5eab7984ef52c0a24c60796557ca69dc6c65749305f24f8ec2000e86f819b2afa0534dc4a7e0c50450ba49903eb7b32ab25d1cc853fd75f97563fde2750ffe5c6140e1165c8e0d48465c7ba4dc9fa0d0463645ea7d38d0180a0e2aef48b2995d3d0b340a7e0d09bf49aea132b338a6ed71f31aa0202289a1e06cea5ee0169fdec85f17813d33ee565aca6b96211c7f75860f325a7795a7314310af99c6f7a8825d869fe9c95d256700509a38cd46b55f5af50fe3a307c8e19de0f47f01f68a203f7403a8c87f2752d9f1f30c766a5c760bcb6d07bee81167ab6a3099ec168ff3b4372f1f54894b2a00131b88197302022b52762e5463198a32ed388975f8fdda7a12d2571806a4b7319eccf5abc0f540ae01eece9fd26181380d3f7581d1d2e739b5b8f53f572f825020de786dd22f4a0b867f8ef3bbe54724d059e330eca99d08668ea2d51449524f6907f41dbdc1b444341cc2b3ac81b1ef3149bfcc2babfe200ec8c5520319b270216bf1efd48cd6f924da17c90c97fee0b289710b0658787b65aa78bfd3373f39f8b72169bbd4291d013c7867ac5f5268fe04036a5fbde68f2359e19419c369ac9b655f01ef5f57ae02004b45d80d548ee70d32bd2cba24c4f3fa9732a598ab6fc4c66810ee8a5c4b8a9db296559f783f1ee6d19270d031a8f61a7a22a063014f9f82b0ddf7981adbafb64227ff41433e2a6c4e1d824e2f08f7d755bdc10cf0b033523bc08667661e50dc8ac79ea63d97c21682e498555891ee304d02948bd3839ab5dbbabeea25c71bfea984e6327c3f0839b74ae10f8a4adca740faf2d749510430638646c146697da89719ac7005b40e5251fdc77660485671482518e068066b1ae66548a597e02f4f8bb6370aaac26837c4670476a48fce0b74dcf32d8113abd06eac149be9149fd421a58362181b4f9b6486ad69d1a78bc24867281c260b6a55789704e1749153116e6dbae0a7f22922752649bce5a101d70e5d0b1171844184fee527e420bce5915b27677e8b2780cb852cabd4588f2470eeea12f701050c738dffe974586aeb3c89630beacad94571402f076e77fcc0d1be92c3126d3e5e9ea644ba397bb09042761cd218ea2ec48abcc51ba3d4d53a10cc76d774a9f49720e065dc82457fdbe8ec3c0988691426706d259660eabc494b4c6a28c3e41ec8224afd0ad25e69e3d2729d3eb617369c9f96e0c441d4de6648bf88240e0c69aa8f4d3bdf9a473fbf409cd17ebc9835dee95a770526bdc683d67ebc6fa93dcdbe706443055869dca8f211a066bb8ef31266a7cc66dc57d0f69045de11d28c9fc6a57a31a392468dc405485fb55ebb7d434d15194fa05c768dd368d4cbf3d88e2794ca64542cd359c55c3ad109949dc32793751ac124eb334b66c3049a7923cd359fb6d3a3fd0a41b3124e3d434f2763e7c04cbe5a2dea87bf5500b774509526f30a65e03081e4a4684f8f166657aad5b745f4b3b01b84f7123e811f5b5564d793362037aa9df300f77f384f750033352cce3df8f278a714c9c440ad77c3ace3db8331fc3ef837f90867388a16bf4fb9583a32517fffe6a13145b655d3b5010aa9ee633e0ef902ee58b69f1a7973e160025db48a455a7d077d25e916559196e3c356292f70cf17c2a468326e0ac8800535e5ce51b1fa4c07e0683c530b4aedf1033d6d447549023892ead37d0b6fa532dee0b178ac40c7bc73f766c03fd16dac196792323459b5b73129d7b826bbaf219f67df20417370dd7dde072e8b8af1acdbf11134b50a17b32c69627c601f49733dd82d6da7b121db6f267607850dada4c79683f8de8649e54c209dbe2d3125ef211d625d02ea6a5553454f92131cb9359b17333e2591bb72ad09bce32b876913b0b061e98d85e62333ab1e32df954cebb267d11d51a10dff0cc9de91cc4d569d6526b1361abb681d92f6ede1a25c46a000ca8111b98ab2bcd6e947fe4a7622d8dbef93119274ad79769fec0df6736374d3de291f6abfd7c597aa8393545250de65efc29a95d32770fa5c61705a8357eccfc75033aa2cf98a34c8246cb4c0f39c2ff86b2a7b98c9fc45a9a7c8f3c45fd37e8467c29fb6de11f1b99e512bf361e7359b3c2d2f690e0bb701b00d3d9aa083e627a624974fae6a01ce354709c27e051ad5d5e3404b62e1254841b1f70f7fbff580e364908a7580b4f76a10e1f793060a23ace5326135376670d7208fc3bc2858375d66125adca07e547ad1ca2f8b6046a76d1c2a1dcd5d31a402e2efbffafcf11e79f2b34fb8fc6d7cd66b03f08bece054355d2ab6eae7cd19ed763e9c08f087e5d1937e771f76dd59388be4002c7338de18f4afa47f1a4d33aaa65359c0f5b706550db44684feb71915f1c34e143d03794ff1a60072de5690bb87b2618b90b19d79e9be54d16928497b0b44355b0b5f33212f620df0a03714220a0f3e51172349a00dd9a7ff0fbdaea71366ed64a0d7eb5c15d4e45e73a42e955a54c25f2886c54ecb60e122786d8041198761ec20ecad4e97502b450bb14338d827dbdc55b57b00c07a6c58c8ef5e34753b7cb59327f1164137c6b9f22d86a5f21e638a3a8cc8b45652557883c643536ef3d9d19b491ffdd37025b0f96f10305a00bc009234f4403accf3de137c3b01347a232f717fbaae5bc9fc93d67f2d7037eeca7fafe613b7b7b7066b25836c8a866320f18b87d94d3299672876f393f52720ab1348d354fb6f8c6d1e712c2edab59cbf30f18c280593a9331596381fc2bbfbdf6ddb7b16bb3f9a529de22498d3185274cd2bad4e604fb4eede695638ca7cf169500dc594f6044c5fa59ea7fe76a4cbc4ad06accedc3fc5ff1d39176374bd22ad464f2514bae32550bd5a5565754047b5acf42d6e2fdba27608c452b66018ed190bc1cf6fafaa1d3d043a09582265922249226e028e7b1d0de65405926b3fcbf767143f90921f6462c18615ea24f741a9d595aac67bda8cc7ffb9e342f4349a8f1b93e71d35bbf5c06b975b830ff8589bf39748e5104b17564eefcde29fe0805cd32719e40431773fb66fc8271106ad4afbf60fce825de6a1d11402f546925f1008d60b6f9e555b987edba01e4f30e568e4a461e7202b02cdcd6a9eeb4f454b7d6d0168305c4018481ce0e8ed0075fed312a0edd95ec85aa0744b6b454ed067a61acccfdff49bf82218ad2b30df4ea8ccdc6020f1001e08a5e254a5337d1b031ae91bfb24774509ea26f06d2746f3163d3b23cdcc7ed69b2cfb449688de9d68040c50751d0a01a2b6010aca6cf4f5fc843687e250a0fde94be03ef78633a90548ea9c0fe7fcaa4402d2694ba76c58429119f6962c75f8b0182d7522fd1db5d966e443b781eb8727b007c599a4d60a07af05f92dc8b7a36d635169765df58ccb5f7a4ec76cb015f834e0ed5db3991a83f583d632d6f8cb3ff52c998ef7c9b48c9e0422ca906b07d50f3afe36801684b5cfd3b31dad337c0acb88d55ab0afd5e4868d8bf3edb49b1c8d2c93759ae6f872608b00f2a5cc4b5ed0729ca72c6f2f8aea5b31d8c6a8595e98c4bcc8401a733001662fffab00ea260afd56b819ccc5bff75ba20a7e5c7323428ca427cfd9010c97bb3332052198b8f5c0f4e803156743f3ffaeb8d071da31e40cb2211143ced9ad859483bad34d1723930ca2538509455d2e548289b05dd63c2d877e35baf892f5908837cdf69bccc4c4bd2e37a9a4b57d224cd8bb259683ab40333861151d7a277cf71b2aa28d2d843201ab6cfd0168f5f44f54d103c5bca8d446ca40efdb467577469597fec6c989686f1759ae2c046ca3d174528536ae9de80e975eb3b428ed7ff9bbf6ce75d85f5821839115468517f85d572a5bf5941c02b9269ac7fdf8e87f582898bd85ff097cd475ae32b88c85932b5447eac8340098ce266bc3dbd9912382dcc158e2dc1a3433ae95df3ca94432d608067f8a7dc6de153270342ba2e467bbd663577a160e0f3b5101442d9fae394a6517c2b326e381e82378af8371cdaa365b31ada5984e857fa5d12babb35fbe184b27d79e62dd568b76896a0c26f0ad7319bf9636406b10d00846ab23dcc8cda92c50dd630ac011b7c71e766ae3f82738b0239715cb2e8b0714237b529bfcbb5aab66720a6d2ea3d37eb9d1b6f3ed619eebc1f2fc171087de3ae3e629ece814118bed3e648aec9cae898f95ac4828542bdd1e072b648482b6255e655333947515548104cd3df0ff5505bc74d86ff26092c7bafd2a3be1fc4824cfe4e2d903c80010af37c95dec06ba4255180fdc937262a3b8d5bbfa4d71e1b8c56da8cfa5dd024b70f086f7a002c502ebd9e03aa75a7fda24356cc123fe744c717a3dd657f8a3561b916ae90b2b103826b14655ffeff0911cc01c131dc88cc5f6e16a7357096736526002246d9566d704ff127a683037245cb03aa26c6758d60b65914fc725e18e0679b6fac8c42157c291d4b1c57580a9e3afa9184e33fa9c3aa195fdd5acfc72b2cd36da62938f3f6598069a8ea1f4941e6757b5021393b1c52e2d4f36b35794ae412b960f6fc300b0e5ccf9c55abb08fa9b6897e65bdb391b4a98389e58f6cbe79410e196c5940e61f9027deef77e0aeebbf28775656b0d235953dab96909c32eeadc3ec61d499ba6aeb3500cef23ab63830f67ec1c07ca5310cffab39ddc9d398ea45f0d50c58f1fd260342e1521ba3184d7e0a8681ade789f4233e80e1d197be272e382ca5daf9f84e8fb1b1b5581a3c326ebdaa1b5df2bd798cda6dea386033de9f1024e910243da9c1be2fab7baebd1de907a8b8fd14fda621dc57f14e278094f577dab7e1e2fc3295088f7396e7665052cae8cb233f47e7b389feda234d44a8c13cc60a30f5541b2d08e173104dc97e44869323bfdc8190e30d94a2fcdf249f3ec78e8ce1b683908df37c6e5c9c47a6bd02037fd201a8577d4f19e5b3488e82fbaa090e9f7e992ce56b02dccbb4ee887fe3504617d125b0f80c66891dd8652097928cd1f66a44f54ff803b7b6d44da01bd5c5298c3b8bc6ead2235e7b2f72b6e4d335a4c8e347c40def417ba64257a879d6a4617c94e22ce9c4f21a95df398b7bdcb7e3c83fe7c0a8f271bbaa2c2606d92a6f3bf7991569a50ce614ed73a86dc7f362308899e325aab00d06a975066f0506a3b30046981d0941f65e17e05c3283d0b5ed6633a705ed90a221cbc892fc5572288183ea006bc83c48fdbe31f23acd3aa55207e7d583f74349cb6609e7849802443b4834fa3fee278020dc40f56c819a21696427905de90d8bde73f31933caf66871aabc6e375aba4e496a7d216d3e6b449f68f2c5c07ce5ebd2c61eef95e7e05d15a8317a831b12666de016eab708c89023223c7f5bb456b1afa758b820e26975a6c16de1fe1eff5ad4786ccdd808601ffa23f59499c8bca5bfd14427c36bd365001134dede46bade845cbc47886e14aebe2fd18d5586a53447c3f205ac4826dc8dba74f5ea47d68675bd31d6d9e3f53663a7aecc26830e91550f4d13295e03e339945bb8482f5d711f17d627f820e7885d909d87bd0a8469373c9b143ed1d6d6f3d9ce392fb2616766c704d730df0635d21670e4dadffdf71105bc0862e24edfd61a21d3c7db4af17feb4f3cdbaae80f10819974cd8d88b3e7ab7426b9d3e0b406c5164386319b992eb176cd92985dbc36bb9410283861bb6a8e0d19112c12caf6a022437bf0cb1535c5ddfe2dc568bc4e62848476a2ac58f539853687be953afbe386cdd05056e2c03fd24734329dcc770b267a533e6c89e268586bcf3d566085e8ff52cfdd55381b7b2c3ef912f505f1f3bc22f77bea575cce54b4a448d289fc5dc41523001aee5670fc33d60dae1d2c3091c55dcd53b73d09e55ec92da41821c2b489b210517b9a7c5e25896def7935bb8b9829b6ef69a2c089406d9dd37ddb81cd1132c174c75158efb2942080c258da1f8fa51d0b5ab5d65321f6313ce10bef5cdafbf8f11b3e665dd24fe6bd5237a9bc0b192008211fe0d84b39ef6334d239bca8d9aa542a64d45ee2ca621baa21550b748e6df9cd5d774038ad340b842ea350ff59b84e6064ea3ed243d20efc70c34dddd863ec86cae1a20b1aefbcd114e0ca4cf463c23703e20d29a040c6027296bf86d66b663f8056ccf729b60f9ba0c07b59d792cc835af2780b62e57aa6c68cb66647f917b00480cd319ef5724ebc2d520398d2100f6821a801321fedf7f5f8a77026ee08d67c1a9f0b0604e0df82b5c0a7d8831dd59e2a708c61a6dcd61cccf25d909f652b14165723f54afceeabb843bd274c479c29752ebcc7d8e169ea64cc8276f17d5d0781d9312d36c40351fb01488c90b3252033be204a88fcb9da8588a45e6fa3143977b620dc5809425603e8536ef99fa3363fa1ff71c4a9d44fd49a8740ca5d1276033a3c0138e36bb1b1e3da927ad76715b36b77ae531de979854f27b1aa75eb3c57f0f7588a78efd7ffba0ca32691f1bd14a8214e6991b140829627cfeb48e4bca471514c3ad197058dc0e82efefd3f19602f11abfa14694c36681a70443d12a482f5312a3f11ebce4d91a8f9cea23e727f2c7dac9cb9fd937e9c4a529de0eac81de3f361eb4884d45df578010f8c905e1f375c80db37e11d6bf084e53ec4e10c7d6ec257933b3910b1a370fef6ede3a692daa1033171e485980227e24a0233d4bfc297d214f63e10b98c1ad8296944a6119f1c19e9b325e33ba33bbf617869720c9309f9d72661a00677c043877ebb90514cc45dbd9d874174ae4cc4b8c4b6d20f72d712c4da6f70fff7073b8742a25866964a1a10388ca8039697019c78b1f0d508dfb2584be729562e449ad3f0640b3d10631e7214196dd9d1164d7cbae378076c670f86e78612bb71412971311f48c73f376ab7da9b8b6e6d17590be6ab3161288e889252f75c9d658ed40803f96228b6213c6ac9e9b922e92069974dbcf3925da8d7098cc23a239ac6af14a3897fd7c58faba25cb2fdc667ec6539655e35477b2d9b7cc5feaa6cc71c05e1e19d3a84cc26e754843686fe4135d78cb6ab9035c47c2c2005261fee668818d8c19110e211bd77de66cb90e39e5beba9a30d90dd7cd799290db4e4574a34eb5f1cddd079107c8fd14d53c7010c5db39b6a5498b58b1895f716bded3427c38828b6b5fe733855b84ca91ad8323541ee6ee57d56f393c490516a380a382f9cafc561a6ead8c1b037225b53f9df7b9a80f789e175a4731ea8e62c4d1eba99c5dda16152822a6ed22437c8ae5278ad039a35cd5b21026e0834b6770581fd71d23817c772c1b7a258d5ba414848cc25c31fc712d72517dbc8d83e3ac75cdc17f1da427d8a3aa394633ce87b2bb1741f0fcb7c2c89b2496b04dfde9193af1380561cf57af97ddccdefa625ce6e156cef618b31efe9fdb9b1977d91ede30e0c25d568db96c0500e0c29b8345163a181a28d6979af11a23a625c4e3f3122d605a895ee51fe6174e38e0c1c5928e7fc91d1ba3491dfeeba10c473c93c7167067485216a727fcfaf788dfdff54aaa195bcdfaf20ce328a8cdbec7036b82afc256289e59b828ae287c42f97f961edf0adcc303dc702f1522bbbf56de9ed0f14af58a6b1335cee3af19da0e09bb5cd50c981520501958c2053a396befc921938854c0c25d02f24b94e43b307fa97c6b50927bfc539c1289164737d7297343ab0d8351f4c1ff88369a6188ef2fddd791e2b1e5137f0e2a6caa7d343f909b1f14a6d838b8ec54d9ca6efd4c94204fdd212b5629cdcb0b1da0ac1be611616d92d67c1332e0dbc188f15e824aa3d588d31952412b3d33d94fdb2d24c4d01b74f00d6cf97effd336a4d064b22f54f304a70272270740e254dd3a6676f46d10b09b704ed985f6bc03ca67088d258a0a2cef42baa93d70a3c1e0ad67eda6455c0acbe0d83ecc06571c86802d0221546b1908d223de306172393339c2f31e7178f56573d461d38f89127ffd6fa8bf8eb5af17d441a3b73719ac961c90c758aba2a40794cc8622fc20f33568464ebb8a46279dc22b7558813633d517a7859fa199ea4c0925149d6207c51d7ed8db4020ad2f8ec8827973016a7ed4f7421e0430465ca023d2475a7f011ca303d6f50ca545c36a0d661a0d791735df98a8c0be6d2f5f3e45aaab847976e8d6d1e8d6d8fdef5a39673fcce748b38c038b6e45520be28c361988f6b84fc05a0237baf6c0be917d10ed9b4aa5d6ee30f3fdb013b9ed885d3a416349b9aa0055c0b72b74d34598484ffade6ce99576677d15c9963295096f3009346f159974508c0bbbf97a0b49e301a7244f66a7fc5db776e468658dc4415b045cacc98670f05557fab0128b154d4e2e83038183e571ade7e2bfd0c7094975fff8b65a41caee5e426bc85e8691b0aa40b8f683d02bb09cb491050ceff47d5d189c6250427fc2f3bda870a1a29bcf7e56e655b476abd575de8645d68ab48152a46787617def65efacf27054c8fbc590c4e210c7b3897b3aeb7edfa18cbb9c99ebd4626adab5cdbcb842722b775a3645d4dba8b502979c7a470dbf44efbc76d126eda10ac4baa073b35bb3f1d66c16483c18c21105d7b4653dfa4e9231e04c18878e1744d5b05bd243a6ce30159e279fba1a28aa860372104420430d7b21f45a53150c36af535206608e06f4531d34e8c2c27c7c7e98bd0bac78f0e76f713f9755dbc3f41dbf9e619b7ce4e23d1008c5503f453794bd08bb1712bd60123d07a2b00b24b07bc0a39039586de382ff1f506432c792178f983f1a09ab8f3a2198204bbe25f2bce6a024c914572a66a0a8713cabdeba17c3bdb037f111ae4f6ff904da48398825c8b89783634911c964599062928cad7e66ad39542e526874bb54fd98e404d4f1b153d5dd44e3a24f3f736ed9bed13e247be609b045b313de0129211effbe450d2830e0e634ac3d3e54be181b76120fb44086b3cf31404b0f8687700b4b148a37045ff0a0ad649ef402797bb1c8ad7dcceff056959ddf84d08bd27a5c25c21f2f2a79adb248dce4bf3c69873cd3523f687805d950f09ea3f2aa5c863650de62a3824b9480ee0b36dc521c4e4b3d2d2275e0fc48b9bbfc990bc2adf1ed609aaeca8c89b7f42d9e292868adbae5efd6bf93ed398438e8f96ce8b9394b4e7baf069cae7143876d31abc42c913a23d79ecdccc58c36b2385938fd34798b2323c608430bf652a00a9f5a942b1d302b4539fb229cf22d55ebbbe5238b0397c69e4d837b93f463cc044bf0e05f1f966e238bc1dbc529922dcca64a54b6eab6f9a22c086a2586767e1a9f2744bb2a23933405dbc5eff612ce4dc9099477d0a8602968410ce9edc8f0a96b339c4d998eb2e81df7fa711c3f560dfce772a80f9c7949435f87e35808ee7a9b7cc39e990ea21437eae16fd77c93d6e64d3bb1dba354fd3512ec4f86e7e967b70442108ed4c63d60de78fa2bb5be6aa3a38e58e5479852612369244fe219725a1d9cb0f104c690c0a8bb831035998394b703cdaa91e4bc2d739923db11b2452ed7d06835f309ea4a0d5c825a34c512a0fd412302d39421b1d61c37a4fd7b5d8107bf59432cd6253735f7ad74f2de1f462d12245a984588354fc0902f3c38925b87edbbf7be28d5b7c3c2e7dbc94fe48a2fefbc420b142b6bc850bd7c1495404e023629e574c5014fc2b11f78ddf963226f2e82aed2b91ae436c2d72125886c1137bd6fe775b3666a5b92620f95938c66894e43b04a97a3310a673b2d6ffa8066c6c1cca0f4f71bc322595b85c42e55e869c1b72fc9414d42a7c7631b8b24db104ebbf1e38264877999e2739ddd44c3954a29f33917172b09bc480667e23d626eca8db6bd5a7cc073ba7090455fa74c7bfb1bb1953ba9a153918d2ede37ffd582ca020eb9a4d7b6e5c3a2bf4cd38f66c2a5bc56fa77c7e5e7cfcbdff82ebe92c0a85b8d7a8e911bfd7fae3c46b75c44de2555218c7a45857220779a15d72f73b7bb73d3bece13769fc5c9370395a05b544ad905e9c2dbc9c8cbba9c2dba94815505932d56427eee2b868b050044bedc72c89812962a8572273d01298bbad79a5262b46961da2fa62672bc6dd8c0fae648a53949c4fe6b29fba4a617af8c9a61acba94628790231475701644f44b8281489ce6a369d600880cfc354757bb8ddfa3bdb49b663d2f74c73e4e45725e7cf39c4a1c1f5201881875756595a9da39abd5b2d249f3f6e8112483e0837ae225cbcbd45b2024a0d60502fe51c3c750e6d6bf75026dd1c36bdb2a75053631dde567621e3cf557b350a255e12af5539b71643c699d26a7872f47303fe53eecf098b20d15847fcdeb9a21a5e0ef43565bb28c5f4d9edb1cced5f9ef296d543b88eba292ba3dc3f6068ed68cddcdb2f7e87419dce79be11eb3e17c8433068e7749f6456fb9f2401e1aa8f47d590baa42e73f9df977daf6f66c7f498722b894137a5c1f7782c4c5c2e35abfc2454bb41d18f010ee5ac6cac86424fd4636435d289b20b0ee8d2cbc3eed84ec76eac266796c5d27ee48cf48d0b366cdee89a5c8191adcd3888e723ef189fbd1f337cc3cacc0ed45f9dd2076b387ae67e480ad94c757fc6b4a3763a10baf134a8238bd70874d16693caee3458a6390420672817bb474ebe63c0603a99f83bbdeca2be44d3dec06b72ef083a062b249432e0c14f6a8fb70675c8ebbd10d7ff6362cb6ade170099dbac7c148acfbaafd61943694f278f5f37576a7271c0bf6bc91db779a6595bebaf3a73a7c8231101ad7513c2437874f3eaa52c8ae1601f74c17a4164cebe96707f2d51255e98bbeed987cbe39809bd82d239ae05e0804b8b649cf062f1595bdaa4f3a22e697a4102f707ce750b3fa3cd10c0815fe512e7c9efdaf712d6a84e63fb47d53040d73b8bee5032e31e898b644119337df5b99a1159062efacfb1347a49f253a4b0a2de8b19000ede20913ad3c26e0b6d057a07d117c77d7c6b979830ce10e4e8a0ed5dd3c914b30a336df4557bfd7fc8de16130c82530235754efd7883a3637859bd97a920f2fc3bd21aa00a4611b3bd5a0283197e549db3f26811657f6c3d5f0e6fd95b2c0b6907764a7a7bd9247dc3024afbf308581e09e3a9722bc5c717a69f419d50d97fa12aedc5ad0f602d72da6aa3a1733564b180c0c2b7990255d21f8fa826f72568544dd3afb0173b837d6ecacd440a5a416767d20655fae69439b5ee8fa36df1d1297361f73f813eb80cb7afdeb193169c2fa961deadd26ddb90d0351a23d1f3ef089fd4e7d4003679c570c64926827f055d78ef8b6e73013cecea119029a3a15dcb3ccf742e82f43949756d04760cd164b79726dcd68570e088dd130da69bb1c560ed4c733e47b28aff2b6121a0760fa1086aa5f2b63481cf2c639ca8bfdc14bab75fa6780521552a9ad31615919c691438ba9133e49a87cf609539bbd8c4cf621cdf0a1a7e80d39688c4d70926e092642cfd2bbfc68ac5035a283da481741d6cbc1b9d079b56a76f11b78ab4f119994d6a1071d18ae8a4f2e929d3fe5e9f15a1cfdf7451260124c83f4a1731d00314ba8689e4b4e6f334e29d2ef3d702d28e563e4436e6b038d5944fd5bba37098b12017efd137c01ee7b587eca1b45f263efa8adbce970662f1fbde165349200432ece0f9c59abc5099b53a292ce77fa1b3ad86b2a9da6bff484654b80aba151e82f5ff4c2799cbe8dda1b1a851b79ab984fdffedf16a83165a1cd3eac5f601cfbb1060a8175ac9f0cf17b8fc5bf982db7c3ffc4fd3b6d51359c06a2f8cac4e9c79631a9df261b65a651ca47d5a6572c0c2957f28a21d5ccf86498588bcf820a7d761e9bc0775e06e88dccbe8d4a8f0b8dda74c78aca2d1decd39e18e7f5d93446e82608096358b4a40a9\n \n \n \n \n 您好, 这里需要密码.\n \n \n \n \n \n \n \n\n","categories":["干货"],"tags":["Interview"]},{"title":"Linux基础(一):常用文件管理命令","url":"/2022/02/21/ubuntu/Linux%E5%9F%BA%E7%A1%801_%E5%B8%B8%E7%94%A8%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86%E5%91%BD%E4%BB%A4/","content":"(1) ctrl c: 取消命令,并且换行(2) ctrl u: 清空本行命令(3) tab键:可以补全命令和文件名,如果补全不了快速按两下tab键,可以显示备选选项(4) ls: 列出当前目录下所有文件,蓝色的是文件夹,白色的是普通文件,绿色的是可执行文件(5) pwd: 显示当前路径(6) cd XXX: 进入XXX目录下, cd .. 返回上层目录(7) cp XXX YYY: 将XXX文件复制成YYY,XXX和YYY可以是一个路径,比如../dir_c/a.txt,表示上层目录下的dir_c文件夹下的文件a.txt(8) mkdir XXX: 创建目录XXX(9) rm XXX: 删除普通文件; rm XXX -r: 删除文件夹(10) mv XXX YYY: 将XXX文件移动到YYY,和cp命令一样,XXX和YYY可以是一个路径;重命名也是用这个命令(11) touch XXX: 创建一个文件(12) cat XXX: 展示文件XXX中的内容(13) 复制文本 windows/Linux下:Ctrl + insert,Mac下:command + c(14) 粘贴文本 windows/Linux下:Shift + insert,Mac下:command + v","categories":["教程"],"tags":["Linux"]},{"title":"Linux基础(二):tmux","url":"/2022/02/21/ubuntu/Linux%E5%9F%BA%E7%A1%802_tmux/","content":"功能: (1) 分屏。 (2) 允许断开Terminal连接后,继续运行进程。结构: 一个tmux可以包含多个session,一个session可以包含多个window,一个window可以包含多个pane。 实例: tmux: session 0: window 0: pane 0 pane 1 pane 2 ... window 1 window 2 ... session 1 session 2 ...操作: (1) tmux:新建一个session,其中包含一个window,window中包含一个pane,pane里打开了一个shell对话框。 (2) 按下Ctrl + a后手指松开,然后按%:将当前pane左右平分成两个pane。 (3) 按下Ctrl + a后手指松开,然后按\"(注意是双引号\"):将当前pane上下平分成两个pane。 (4) Ctrl + d:关闭当前pane;如果当前window的所有pane均已关闭,则自动关闭window;如果当前session的所有window均已关闭,则自动关闭session。 (5) 鼠标点击可以选pane。 (6) 按下ctrl + a后手指松开,然后按方向键:选择相邻的pane。 (7) 鼠标拖动pane之间的分割线,可以调整分割线的位置。 (8) 按住ctrl + a的同时按方向键,可以调整pane之间分割线的位置。 (9) 按下ctrl + a后手指松开,然后按z:将当前pane全屏/取消全屏。 (10) 按下ctrl + a后手指松开,然后按d:挂起当前session。 (11) tmux a:打开之前挂起的session。 (12) 按下ctrl + a后手指松开,然后按s:选择其它session。 方向键 —— 上:选择上一项 session/window/pane 方向键 —— 下:选择下一项 session/window/pane 方向键 —— 右:展开当前项 session/window 方向键 —— 左:闭合当前项 session/window (13) 按下Ctrl + a后手指松开,然后按c:在当前session中创建一个新的window。 (14) 按下Ctrl + a后手指松开,然后按w:选择其他window,操作方法与(12)完全相同。 (15) 按下Ctrl + a后手指松开,然后按PageUp:翻阅当前pane内的内容。 (16) 鼠标滚轮:翻阅当前pane内的内容。 (17) 在tmux中选中文本时,需要按住shift键。(仅支持Windows和Linux,不支持Mac,不过该操作并不是必须的,因此影响不大) (18) tmux中复制/粘贴文本的通用方式: (1) 按下Ctrl + a后松开手指,然后按[ (2) 用鼠标选中文本,被选中的文本会被自动复制到tmux的剪贴板 (3) 按下Ctrl + a后松开手指,然后按],会将剪贴板中的内容粘贴到光标处","categories":["教程"],"tags":["Linux","tmux"]},{"title":"Linux基础(三):vim","url":"/2022/02/21/ubuntu/Linux%E5%9F%BA%E7%A1%803_vim/","content":"功能: (1) 命令行模式下的文本编辑器。 (2) 根据文件扩展名自动判别编程语言。支持代码缩进、代码高亮等功能。 (3) 使用方式:vim filename 如果已有该文件,则打开它。 如果没有该文件,则打开个一个新的文件,并命名为filename模式: (1) 一般命令模式 默认模式。命令输入方式:类似于打游戏放技能,按不同字符,即可进行不同操作。可以复制、粘贴、删除文本等。 (2) 编辑模式 在一般命令模式里按下i,会进入编辑模式。 按下ESC会退出编辑模式,返回到一般命令模式。 (3) 命令行模式 在一般命令模式里按下:/?三个字母中的任意一个,会进入命令行模式。命令行在最下面。 可以查找、替换、保存、退出、配置编辑器等。操作: (1) i:进入编辑模式 (2) ESC:进入一般命令模式 (3) h 或 左箭头键:光标向左移动一个字符 (4) j 或 向下箭头:光标向下移动一个字符 (5) k 或 向上箭头:光标向上移动一个字符 (6) l 或 向右箭头:光标向右移动一个字符 (7) n<Space>:n表示数字,按下数字后再按空格,光标会向右移动这一行的n个字符 (8) 0 或 功能键[Home]:光标移动到本行开头 (9) $ 或 功能键[End]:光标移动到本行末尾 (10) G:光标移动到最后一行 (11) :n 或 nG:n为数字,光标移动到第n行 (12) gg:光标移动到第一行,相当于1G (13) n<Enter>:n为数字,光标向下移动n行 (14) /word:向光标之下寻找第一个值为word的字符串。 (15) ?word:向光标之上寻找第一个值为word的字符串。 (16) n:重复前一个查找操作 (17) N:反向重复前一个查找操作 (18) :n1,n2s/word1/word2/g:n1与n2为数字,在第n1行与n2行之间寻找word1这个字符串,并将该字符串替换为word2 (19) :1,$s/word1/word2/g:将全文的word1替换为word2 (20) :1,$s/word1/word2/gc:将全文的word1替换为word2,且在替换前要求用户确认。 (21) v:选中文本 (22) d:删除选中的文本 (23) dd: 删除当前行 (24) y:复制选中的文本 (25) yy: 复制当前行 (26) p: 将复制的数据在光标的下一行/下一个位置粘贴 (27) u:撤销 (28) Ctrl + r:取消撤销 (29) 大于号 >:将选中的文本整体向右缩进一次 (30) 小于号 <:将选中的文本整体向左缩进一次 (31) :w 保存 (32) :w! 强制保存 (33) :q 退出 (34) :q! 强制退出 (35) :wq 保存并退出 (36) :set paste 设置成粘贴模式,取消代码自动缩进 (37) :set nopaste 取消粘贴模式,开启代码自动缩进 (38) :set nu 显示行号 (39) :set nonu 隐藏行号 (40) gg=G:将全文代码格式化 (41) :noh 关闭查找关键词高亮 (42) Ctrl + q:当vim卡死时,可以取消当前正在执行的命令异常处理: 每次用vim编辑文件时,会自动创建一个.filename.swp的临时文件。 如果打开某个文件时,该文件的swp文件已存在,则会报错。此时解决办法有两种: (1) 找到正在打开该文件的程序,并退出 (2) 直接删掉该swp文件即可","categories":["教程"],"tags":["Linux","vim"]},{"title":"Linux基础(五):ssh","url":"/2022/02/21/ubuntu/Linux%E5%9F%BA%E7%A1%805_ssh/","content":"ssh登录基本用法远程登录服务器:\nssh user@hostname\n\nuser : 用户名\nhostname : IP地址或域名\n\n第一次登录时会提示:\nThe authenticity of host '123.57.47.211 (123.57.47.211)' can't be established.ECDSA key fingerprint is SHA256:iy237yysfCe013/l+kpDGfEG9xxHxm0dnxnAbJTPpG8.Are you sure you want to continue connecting (yes/no/[fingerprint])?\n输入yes,然后回车即可。这样会将该服务器的信息记录在~/.ssh/known_hosts文件中。\n然后输入密码即可登录到远程服务器中。\n默认登录端口号为22。如果想登录某一特定端口:\nssh user@hostname -p 22\n\n配置文件创建文件~/.ssh/config。\n然后在文件中输入:\nHost myserver1 HostName IP地址或域名 User 用户名Host myserver2 HostName IP地址或域名 User 用户名\n之后再使用服务器时,可以直接使用别名myserver1、myserver2。\n\n密钥登录创建密钥:\nssh-keygen\n然后一直回车即可。\n执行结束后,~/.ssh/目录下会多两个文件:\n\nid_rsa:私钥\n\nid_rsa.pub:公钥\n\n\n之后想免密码登录哪个服务器,就将公钥传给哪个服务器即可。\n例如,想免密登录myserver服务器。则将公钥中的内容,复制到myserver中的~/.ssh/authorized_keys文件里即可。\n也可以使用如下命令一键添加公钥:\nssh-copy-id myserver\n\n执行命令命令格式:ssh user@hostname command例如:ssh user@hostname ls -a或者# 单引号中的$i可以求值ssh myserver 'for ((i = 0; i < 10; i ++ )) do echo $i; done'或者# 双引号中的$i不可以求值ssh myserver \"for ((i = 0; i < 10; i ++ )) do echo $i; done\"\n\nscp传文件基本用法命令格式:scp source destination将source路径下的文件复制到destination中\n一次复制多个文件:scp source1 source2 destination复制文件夹:scp -r ~/tmp myserver:/home/acs/将本地家目录中的tmp文件夹复制到myserver服务器中的/home/acs/目录下。scp -r ~/tmp myserver:homework/将本地家目录中的tmp文件夹复制到myserver服务器中的~/homework/目录下。scp -r myserver:homework .将myserver服务器中的~/homework/文件夹复制到本地的当前路径下。\n指定服务器的端口号:scp -P 22 source1 source2 destination注意: scp的-r -P等参数尽量加在source和destination之前。\n使用scp配置其他服务器的vim和tmuxscp ~/.vimrc ~/.tmux.conf myserver:","categories":["教程"],"tags":["Linux","ssh"]},{"title":"Linux基础(六):Git","url":"/2022/02/21/ubuntu/Linux%E5%9F%BA%E7%A1%806_git/","content":"git基本概念\n工作区:仓库的目录。工作区是独立于各个分支的。\n暂存区:数据暂时存放的区域,类似于工作区写入版本库前的缓存区。暂存区是独立于各个分支的。\n版本库:存放所有已经提交到本地仓库的代码版本\n版本结构:树结构,树中每个节点代表一个代码版本。\n\ngit常用命令\ngit config --global user.name xxx:设置全局用户名,信息记录在~/.gitconfig文件中\ngit config --global user.email [email protected]:设置全局邮箱地址,信息记录在~/.gitconfig文件中\ngit init:将当前目录配置成git仓库,信息记录在隐藏的.git文件夹中\ngit add XX:将XX文件添加到暂存区\ngit add .:将所有待加入暂存区的文件加入暂存区\n\n\ngit rm --cached XX:将文件从仓库索引目录中删掉\ngit commit -m \"给自己看的备注信息\":将暂存区的内容提交到当前分支\ngit status:查看仓库状态\ngit diff XX:查看XX文件相对于暂存区修改了哪些内容\ngit log:查看当前分支的所有版本\ngit reflog:查看HEAD指针的移动历史(包括被回滚的版本)\ngit reset --hard HEAD^ 或 git reset --hard HEAD~:将代码库回滚到上一个版本\ngit reset --hard HEAD^^:往上回滚两次,以此类推\ngit reset --hard HEAD~100:往上回滚100个版本\ngit reset --hard 版本号:回滚到某一特定版本\n\n\ngit checkout — XX或git restore XX:将XX文件尚未加入暂存区的修改全部撤销\ngit remote add origin [email protected]:xxx/XXX.git:将本地仓库关联到远程仓库\ngit push -u (第一次需要-u以后不需要):将当前分支推送到远程仓库\ngit push origin branch_name:将本地的某个分支推送到远程仓库\n\n\ngit clone [email protected]:xxx/XXX.git:将远程仓库XXX下载到当前目录下\ngit checkout -b branch_name:创建并切换到branch_name这个分支\ngit branch:查看所有分支和当前所处分支\ngit checkout branch_name:切换到branch_name这个分支\ngit merge branch_name:将分支branch_name合并到当前分支上\ngit branch -d branch_name:删除本地仓库的branch_name分支\ngit branch branch_name:创建新分支\ngit push --set-upstream origin branch_name:设置本地的branch_name分支对应远程仓库的branch_name分支\ngit push -d origin branch_name:删除远程仓库的branch_name分支\ngit pull:将远程仓库的当前分支与本地仓库的当前分支合并\ngit pull origin branch_name:将远程仓库的branch_name分支与本地仓库的当前分支合并\n\n\ngit branch --set-upstream-to=origin/branch_name1 branch_name2:将远程的branch_name1分支与本地的branch_name2分支对应\ngit checkout -t origin/branch_name: 将远程的branch_name分支拉取到本地\ngit stash:将工作区和暂存区中尚未提交的修改存入栈中\ngit stash apply:将栈顶存储的修改恢复到当前分支,但不删除栈顶元素\ngit stash drop:删除栈顶存储的修改\ngit stash pop:将栈顶存储的修改恢复到当前分支,同时删除栈顶元素\ngit stash list:查看栈中所有元素\n\n","categories":["教程"],"tags":["Linux","Git"]},{"title":"Linux基础(七):管道、环境变量与常用命令","url":"/2022/02/21/ubuntu/Linux%E5%9F%BA%E7%A1%807_%E7%AE%A1%E9%81%93%E3%80%81%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E4%B8%8E%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/","content":"管道、环境变量与常用命令管道概念管道类似于文件重定向,可以将前一个命令的stdout重定向到下一个命令的stdin。\n要点\n管道命令仅处理stdout,会忽略stderr。\n管道右边的命令必须能接受stdin。\n多个管道命令可以串联。\n\n与文件重定向的区别\n文件重定向左边为命令,右边为文件。\n管道左右两边均为命令,左边有stdout,右边有stdin。举例统计当前目录下所有python文件的总行数,其中find、xargs、wc等命令可以参考常用命令这一节内容。find . -name '*.py' | xargs cat | wc -l\n\n\n\n环境变量概念Linux系统中会用很多环境变量来记录配置信息。环境变量类似于全局变量,可以被各个进程访问到。我们可以通过修改环境变量来方便地修改系统配置。\n查看列出当前环境下的所有环境变量:env # 显示当前用户的变量set # 显示当前shell的变量,包括当前用户的变量;export # 显示当前导出成用户变量的shell变量输出某个环境变量的值:echo $PATH\n修改环境变量的定义、修改、删除操作可以参考shell语法——变量这一节的内容。\n为了将对环境变量的修改应用到未来所有环境下,可以将修改命令放到~/.bashrc文件中。修改完~/.bashrc文件后,记得执行source ~/.bashrc,来将修改应用到当前的bash环境下。\n为何将修改命令放到~/.bashrc,就可以确保修改会影响未来所有的环境呢?\n\n每次启动bash,都会先执行~/.bashrc。\n每次ssh登陆远程服务器,都会启动一个bash命令行给我们。\n每次tmux新开一个pane,都会启动一个bash命令行给我们。\n所以未来所有新开的环境都会加载我们修改的内容。常见环境变量\n\n\nHOME:用户的家目录。\nPATH:可执行文件(命令)的存储路径。路径与路径之间用:分隔。当某个可执行文件同时出现在多个路径中时,会选择从左到右数第一个路径中的执行。下列所有存储路径的环境变量,均采用从左到右的优先顺序。\nLD_LIBRARY_PATH:用于指定动态链接库(.so文件)的路径,其内容是以冒号分隔的路径列表。\nC_INCLUDE_PATH:C语言的头文件路径,内容是以冒号分隔的路径列表。\nCPLUS_INCLUDE_PATH:CPP的头文件路径,内容是以冒号分隔的路径列表。\nPYTHONPATH:Python导入包的路径,内容是以冒号分隔的路径列表。\nJAVA_HOME:jdk的安装目录。\nCLASSPATH:存放Java导入类的路径,内容是以冒号分隔的路径列表。\n\n常用命令Linux命令非常多,本节讲解几个常用命令。其他命令依赖于大家根据实际操作环境,边用边查。\n系统状况\ntop:查看所有进程的信息(Linux的任务管理器)\n\n\n打开后,输入M:按使用内存排序\n打开后,输入P:按使用CPU排序\n打开后,输入q:退出\n\n\ndf -h:查看硬盘使用情况\nfree -h:查看内存使用情况\ndu -sh:查看当前目录占用的硬盘空间\nps aux:查看所有进程\nkill -9 pid:杀死编号为pid的进程\n\n\n传递某个具体的信号:kill -s SIGTERM pid\n\n\nnetstat -nt:查看所有网络连接\nw:列出当前登陆的用户\nping www.baidu.com:检查是否连网\n\n文件权限\nchmod:修改文件权限\n\n\nchmod +x xxx:给xxx添加可执行权限\nchmod -x xxx:去掉xxx的可执行权限\nchmod 777 xxx:将xxx的权限改成777\nchmod 777 xxx -R:递归修改整个文件夹的权限\n\n文件检索\nfind /path/to/directory/ -name '*.py':搜索某个文件路径下的所有*.py文件\ngrep xxx:从stdin中读入若干行数据,如果某行中包含xxx,则输出该行;否则忽略该行。\nwc:统计行数、单词数、字节数\n\n\n既可以从stdin中直接读入内容;也可以在命令行参数中传入文件名列表;\nwc -l:统计行数\nwc -w:统计单词数\nwc -c:统计字节数\n\n\ntree:展示当前目录的文件结构\n\n\ntree /path/to/directory/:展示某个目录的文件结构\ntree -a:展示隐藏文件\n\n\nag xxx:搜索当前目录下的所有文件,检索xxx字符串\ncut:分割一行内容\n\n\n从stdin中读入多行数据\necho $PATH | cut -d ':' -f 3,5:输出PATH用:分割后第3、5列数据\necho $PATH | cut -d ':' -f 3-5:输出PATH用:分割后第3-5列数据\necho $PATH | cut -c 3,5:输出PATH的第3、5个字符\necho $PATH | cut -c 3-5:输出PATH的第3-5个字符\n\n\nsort:将每行内容按字典序排序\n\n\n可以从stdin中读取多行数据\n可以从命令行参数中读取文件名列表\n\n\nxargs:将stdin中的数据用空格或回车分割成命令行参数\n\n\nfind . -name '*.py' | xargs cat | wc -l:统计当前目录下所有python文件的总行数查看文件内容\n\n\nmore:浏览文件内容\n\n\n回车:下一行\n空格:下一页\nb:上一页\nq:退出\n\n\nless:与more类似,功能更全\n\n\n回车:下一行\ny:上一行\nPage Down:下一页\nPage Up:上一页\nq:退出\n\n\nhead -3 xxx:展示xxx的前3行内容\n\n\n同时支持从stdin读入内容\n\n\ntail -3 xxx:展示xxx末尾3行内容\n\n\n同时支持从stdin读入内容\n\n用户相关\nhistory:展示当前用户的历史操作。内容存放在~/.bash_history中\n\n工具\nmd5sum:计算md5哈希值\n\n可以从stdin读入内容\n也可以在命令行参数中传入文件名列表;\n\n\ntime command:统计command命令的执行时间\nipython3:交互式python3环境。可以当做计算器,或者批量管理文件。\n! echo \"Hello World\":!表示执行shell脚本\n\n\nwatch -n 0.1 command:每0.1秒执行一次command命令\ntar:压缩文件\n\ntar -zcvf xxx.tar.gz /path/to/file/*:压缩\ntar -zxvf xxx.tar.gz:解压缩\n\n\ndiff xxx yyy:查找文件xxx与yyy的不同点\n\n安装软件\nsudo command:以root身份执行command命令\napt-get install xxx:安装软件\npip install xxx --user --upgrade:安装python包\n\n","categories":["教程"],"tags":["Linux"]},{"title":"Linux基础(八):租云服务器及配置docker环境","url":"/2022/02/21/ubuntu/Linux%E5%9F%BA%E7%A1%808_%E7%A7%9F%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%8F%8A%E9%85%8D%E7%BD%AEdocker/","content":"概述云平台的作用:存放我们的docker容器,让计算跑在云端。获得公网IP地址,让每个人可以访问到我们的服务。\n任选一个云平台即可,推荐配置:1核 2GB(后期可以动态扩容,前期配置低一些没关系)网络带宽采用按量付费,最大带宽拉满即可(费用取决于用量,与最大带宽无关)系统版本:ubuntu 20.04 LTS(推荐用统一版本,避免后期出现配置不兼容的问题)\n租云平台阿里云阿里云地址:https://www.aliyun.com/\n创建工作用户username(username改成你自己的)并赋予sudo权限登录到新服务器。打开Terminal,然后:ssh [email protected] # xxx.xxx.xxx.xxx替换成新服务器的公网IP创建username用户:adduser username # 创建用户acsusermod -aG sudo acs # 给用户acs分配sudo权限\n配置免密登录方式退回Terminal,然后配置username用户的别名和免密登录,可以参考ssh——ssh登录。\n配置新服务器的工作环境将Terminal的配置传到新服务器上:scp .bashrc .vimrc .tmux.conf server_name: # server_name需要换成自己配置的别名\n安装tmux和docker登录自己的服务器,然后安装tmux:sudo apt-get updatesudo apt-get install tmux打开tmux。(养成好习惯,所有工作都在tmux里进行,防止意外关闭终端后,工作进度丢失)\n然后在tmux中根据docker安装教程安装docker即可。\n腾讯云腾讯云地址:https://cloud.tencent.com/\n华为云华为云地址:https://www.huaweicloud.com/\ndocker教程将当前用户添加到docker用户组为了避免每次使用docker命令都需要加上sudo权限,可以将当前用户加入安装中自动创建的docker用户组(可以参考官方文档):sudo usermod -aG docker $USER\n镜像(images)\ndocker pull ubuntu:20.04:拉取一个镜像\n\ndocker images:列出本地所有镜像\n\ndocker image rm ubuntu:20.04 或 docker rmi ubuntu:20.04:删除镜像ubuntu:20.04\ndocker [container] commit CONTAINER IMAGE_NAME:TAG:创建某个container的镜像\ndocker save -o ubuntu_20_04.tar ubuntu:20.04:将镜像ubuntu:20.04导出到本地文件ubuntu_20_04.tar中\ndocker load -i ubuntu_20_04.tar:将镜像ubuntu:20.04从本地文件ubuntu_20_04.tar中加载出来\n\n容器(container)\ndocker [container] create -it ubuntu:20.04:利用镜像ubuntu:20.04创建一个容器。\n\ndocker ps -a:查看本地的所有容器\n\ndocker [container] start CONTAINER:启动容器\ndocker [container] stop CONTAINER:停止容器\ndocker [container] restart CONTAINER:重启容器\ndocker [contaienr] run -itd ubuntu:20.04:创建并启动一个容器\ndocker [container] attach CONTAINER:进入容器\n先按Ctrl-p,再按Ctrl-q可以挂起容器\n\n\ndocker [container] exec CONTAINER COMMAND:在容器中执行命令\ndocker [container] rm CONTAINER:删除容器\ndocker container prune:删除所有已停止的容器\ndocker export -o xxx.tar CONTAINER:将容器CONTAINER导出到本地文件xxx.tar中\ndocker import xxx.tar image_name:tag:将本地文件xxx.tar导入成镜像,并将镜像命名为image_name:tag\ndocker export/import与docker save/load的区别:\n\nexport/import会丢弃历史记录和元数据信息,仅保存容器当时的快照状态\n\nsave/load会保存完整记录,体积更大\n\n\n\ndocker top CONTAINER:查看某个容器内的所有进程\n\ndocker stats:查看所有容器的统计信息,包括CPU、内存、存储、网络等信息\ndocker cp xxx CONTAINER:xxx 或 docker cp CONTAINER:xxx xxx:在本地和容器间复制文件\ndocker rename CONTAINER1 CONTAINER2:重命名容器\ndocker update CONTAINER --memory 500MB:修改容器限制\n\n实战进入AC Terminal,然后:scp /var/lib/acwing/docker/images/docker_lesson_1_0.tar server_name: # 将镜像上传到自己租的云端服务器ssh server_name # 登录自己的云端服务器docker load -i docker_lesson_1_0.tar # 将镜像加载到本地docker run -p 20000:22 --name my_docker_server -itd docker_lesson:1.0 # 创建并运行docker_lesson:1.0镜像docker attach my_docker_server # 进入创建的docker容器passwd # 设置root密码去云平台控制台中修改安全组配置,放行端口20000。\n返回AC Terminal,即可通过ssh登录自己的docker容器:ssh [email protected] -p 20000 # 将xxx.xxx.xxx.xxx替换成自己租的服务器的IP地址然后,可以仿照上节课内容,创建工作账户acs。\n最后,可以参考ssh——ssh登录配置docker容器的别名和免密登录。\n小Tips如果apt-get下载软件速度较慢,可以参考清华大学开源软件镜像站中的内容,修改软件源。\n","categories":["教程"],"tags":["Linux","docker"]},{"title":"Neovim + Ubuntu快速搭建教程","url":"/2021/04/30/ubuntu/nvim_linux/","content":"Neovim + Ubuntu快速搭建教程先说下目的吧,因为自己经常需要在GPU服务器上跑DL模型,大多数时候是通过本地debug之后的代码上传到服务器来跑。这样最大的问题就是效率太低,每次出错都要把代码拉下来修改。其次呢,因为是通过终端来操作大部分使用的是vim编辑器。说实话,写了这么多年的代码了vim用的是相当的不熟练。所以想学一学vim并且想要找到一个好的插件,能够满足我的一下需求:\n\n[x] 方便文件的操作(增删改查)\n[x] 支持python自动补全\n[ ] 可以debug\n[x] 以上操作均是通过终端实现\n\n正好在b站看到大佬TheCW出得Neovim教程发现vim效率确实高,于是花了几天自己动手搭建了一次。中间多多少少遇到了一点坑,总结一下为了以后配置更快点吧。\n\nInstallation\n[ ] Ubuntu 18.04 LST\n[ ] Neovim 0.5.0+\n\n安装Neovim这里遇到了一点坑,就是一开始使用命令sudo apt-get install neovim无奈可能是apt版本太低,导致安装的Neovim版本为0.2.x。GooGle到一篇文章推荐使用ppa安装,命令如下:sudo add-apt-repository ppa:neovim-ppa/unstablesudo apt updatesudo apt install -y neovim第一行指定为unstable可下载最新的版本.\n安装Nodejs这里是踩的第二个坑,由于需要配置许多插件,其中coc.nvim在启动nvim时老弹出错误,搞了半天才发现是Nodejs版本太低。需要12.12.x以上,但是我这台服务器已经装了6.x的版本,一开始在配环境变量上耽误了许多时间,但还是没搞定。最后采用了另外一种方法,通过nvm安装。这里介绍一下,nvm是针对nodejs的专门软件,可以很方便的安装卸载各个版本。这里的命令如下:wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash其中 v0.38.0为nvm的版本,可通过这里查看Lastest nvm version\n安装好nvm之后可安装nodejs了,这里安装的版本为v14.17.3nvm install <version-number>nvm use <version-number>\n下载vim-plug插件github 自己搜吧\n设置nvim的配置文件+插件与vim不同的是,nvim的配置文件在~/.config/nvim/init.vim,vim在~/.vim/.vimrc首先,进入.config文件夹并clone我放在GitHub上的配置文件cd ~/.config/git clone https://github.com/wudi1183456665/nvim.gitcd nvimmkdir plugged tmp\n启动nvim及安装插件首次启动时可通过终端输入nvim启动,强迫症的我习惯了之前的vim启动,这里可以修改zsh的启动文件打开vim ~/.zshrc\n添加alias vim=’nvim’\n插件的安装也很容易,主要就是网速太慢进入nvim,输入:PlugInstall 应该会自动安装,安装完成后就可以愉快的使用了。\n","categories":["干货"],"tags":["ubuntu","neovim"]},{"title":"English Interview","url":"/2021/04/30/%E5%8D%9A%E5%A3%AB%E7%94%B3%E8%AF%B7/%E8%8B%B1%E8%AF%AD%E9%9D%A2%E8%AF%95%E9%AB%98%E9%A2%91%E9%97%AE%E9%A2%98/","content":"\n fdce470aa48e507ad61ad4892d2912452abbc4c68792d922f0f76e59c9d0840686dceffd1dabec383d0d95fb7fe6dcd72d34becd6212faf66f2b7d055e48652e115dcfc261fd144f4b7a9ff38c681c97efa839fcfcfa89f4699c83f46bd406a1a309eabbc1cdfd65cf2ad1e3ebc7764f7bd2e7b79af4b9982f5dfa46ccbc4110db1421f53a95d06be71e626c07a2328effccb331a58283ee0d9a98bc8d9f524b19334178ac17fcd057e99a0e95d8f7a7554050bbaa156e649624391ae0045c42f63bc18ad500a91980c6267634bdea12788c55f05f3cfed24ea9f1546b4c8b1ab1b78d27c283be017c6317bad262b87bd6658a7c1d2b61e5c6a740ffc502df99b171c43cfdb39baa7c9131fe2e07093c9becc5170bb6033f16dad318714459867a642e6f73652d792d8cb8f1531efb2e9dfd9fb5e5cf70ab3c362139aa4361f0089ec208fe395142d91db43e632d104211c0b053586799e09554fd04d52d34eee30c0ebc7c8a43f34005aebe92d073ffad46a4be029cb43d5908f54b818ec3791bad8649407c61f3d27353b28884af2a4b356995ceaf11358f258a79cf285689199fa371c1c16faa7bdf92a8f6bc8ef560be1d1e46d2cea8293b171bc082361da7047db1eb79f7d43e0cc4ac5ddb0b1655446a78a3881eb15e669498314eadc72ed62e9107b7e57066eea1e27d0c5e8256a930b0142466ec9646e49bcbd1755bbe9530e22b1e604b186f0cab28683ee0aa0df0ee2a704dd2704384b58f39508b441fe6e5866a196605e4b9f8ca86668da1e481c209d3c05a3848eb3113e9403ecbaf8d9dcf354c3de2024f4f2bcd1c68ad05098c80f84819968d922618030ddbef2b87a73c539147e6ef75160302e6d22f29948907d37d628f153dd6b307973b825aa0a7be918ad3df7ac59a304b72d8d47c97288b244462a1abdd1e1f218fd41e4ba9c3213ca2477bf37db6db236735122632010cd860d44e17bba6721cedb7f1bd1c2f3f68627e3448c58c253ac1b4c32ae10f03f5a94643f30830b3979bb8b09a0e7748200181ce68787456bacd09bb07bc6c4a5fa64d26ace43a2cc8be671f69fbeba1d0443e2d85faf2ae22e65297e72795165d9fcc3f58e81755effacebbbf1580d255810331c44a272f0bc7334b7ff50c8215d86747cd1121ed778b4606e7874c5cc906db5db9149552ae521e98239c812af99e709fcf483bf60385110b8b3b91ab86638cdd1e23a92a14db0fb546494de0b042ac616f7f571212c6deeaab6487b62a154ac886f716ee58a041cd0e2e2403f3fdca8312fdf0df859f7cf8929f16e0fa3a91cf9594ca7e2dc61b284dd7e096ea5cfe8cd7423cdad7e863add6fae98fbea620715c59af5744ada460ec2564ebe23319720423a881a592e83e8a3d9d2295d4417221cf28c2cdc7b5b4dad15cc2e150910bf4e0096eacfa180e8d3433078fbb9b59cf15bd7aaeedcc23e665c7f7c4b14b21190e86deec95fbb406939124946374e9c8800087f080adb4f990be6d72a0859dee3e725006642698012756c66f44235bd9d1414e51c6fdfd65cac57a72f0031784428e31e5841ea6d7ef799a5f4d64065af22a2e8d9bec5051f66ca7dd5da5740edf149f4eab32c696c86bad87a5f426ce00b0909366e41e8adc0591325dff119b7b034a11c3b261ff24168f391f76f4a0071ae097094f760d4d6b969919830fd04efeef5a6487a56895d56429120d0aef166983dbaaff16da37854b7693e8bbf4cafe53016eeb051a011782054ba2872edd3ab42b40b2ff72eb264f4bffffe9297ec0213de491616582e869694e429c8e47875f02a3c877e3236db1fa19585c22b46ada05e8607cc35c679b624a0233d4f73bef6435e74a0a5d5e46a36f0e3b1517f1d7d8de66e2ef2d0b7dc8ef158216e68adbf12a616550ffcadda2ae16b4afa7da8c511b58a777ebccc37bafbdb442d6e3af446df5148bc731f7e13caf77d2e3800f49c5b40df78a2f1892416004067f1f7253321aef0159575cd02b1bc5526b2f2eabc7edb4f7545aee057beb8d5c0669adf1ac63c259c47b85313b870fdb60e784aaab49f1b9ea1045030033484e1acf0243813ff9008be83336b2fb13400814d513563c525c2b8644ba9520c85531a829128f74aba603050a9f136b9f2db0e16a9cd79e9c6df93893870eac66034af734d7cf2208c0a296da28744dd13715ce8d78f8563f49b68dfb488eb5eab7984ef52c0a24c60796557ca69dc6c65749305f24f8ec2000e86f819b2afa0534dc4a7e0c50450ba49903eb7b32ab25d1cc853fd75f97563fde2750ffe5c6140e1165c8e0d48465c7ba4dc9fa0d0463645ea7d38d0180a0e2aef48b2995d3d0b340a7e0d09bf49aea132b338a6ed71f31aa0202289a1e06cea5ee0169fdec85f17813d33ee565aca6b96211c7f75860f325a7795a7314310af99c6f7a8825d869fe9c95d256700509a38cd46b55f5af50fe3a307c8e19de0f47f01f68a203f7403a8c87f2752d9f1f30c766a5c760bcb6d07bee81167ab6a3099ec168ff3b4372f1f54894b2a00131b88197302022b52762e5463198a32ed388975f8fdda7a12d2571806a4b7319eccf5abc0f540ae01eece9fd26181380d3f7581d1d2e739b5b8f53f572f825020de786dd22f4a0b867f8ef3bbe54724d059e330eca99d08668ea2d51449524f6907f41dbdc1b444341cc2b3ac81b1ef3149bfcc2babfe200ec8c5520319b270216bf1efd48cd6f924da17c90c97fee0b289710b0658787b65aa78bfd3373f39f8b72169bbd4291d013c7867ac5f5268fe04036a5fbde68f2359e19419c369ac9b655f01ef5f57ae02004b45d80d548ee70d32bd2cba24c4f3fa9732a598ab6fc4c66810ee8a5c4b8a9db296559f783f1ee6d19270d031a8f61a7a22a063014f9f82b0ddf7981adbafb64227ff41433e2a6c4e1d824e2f08f7d755bdc10cf0b033523bc08667661e50dc8ac79ea63d97c21682e498555891ee304d02948bd3839ab5dbbabeea25c71bfea984e6327c3f0839b74ae10f8a4adca740faf2d749510430638646c146697da89719ac7005b40e5251fdc77660485671482518e068066b1ae66548a597e02f4f8bb6370aaac26837c4670476a48fce0b74dcf32d8113abd06eac149be9149fd421a58362181b4f9b6486ad69d1a78bc24867281c260b6a55789704e1749153116e6dbae0a7f22922752649bce5a101d70e5d0b1171844184fee527e420bce5915b27677e8b2780cb852cabd4588f2470eeea12f701050c738dffe974586aeb3c89630beacad94571402f076e77fcc0d1be92c3126d3e5e9ea644ba397bb09042761cd218ea2ec48abcc51ba3d4d53a10cc76d774a9f49720e065dc82457fdbe8ec3c0988691426706d259660eabc494b4c6a28c3e41ec8224afd0ad25e69e3d2729d3eb617369c9f96e0c441d4de6648bf88240e0c69aa8f4d3bdf9a473fbf409cd17ebc9835dee95a770526bdc683d67ebc6fa93dcdbe706443055869dca8f211a066bb8ef31266a7cc66dc57d0f69045de11d28c9fc6a57a31a392468dc405485fb55ebb7d434d15194fa05c768dd368d4cbf3d88e2794ca64542cd359c55c3ad109949dc32793751ac124eb334b66c3049a7923cd359fb6d3a3fd0a41b3124e3d434f2763e7c04cbe5a2dea87bf5500b774509526f30a65e03081e4a4684f8f166657aad5b745f4b3b01b84f7123e811f5b5564d793362037aa9df300f77f384f750033352cce3df8f278a714c9c440ad77c3ace3db8331fc3ef837f90867388a16bf4fb9583a32517fffe6a13145b655d3b5010aa9ee633e0ef902ee58b69f1a7973e160025db48a455a7d077d25e916559196e3c356292f70cf17c2a468326e0ac8800535e5ce51b1fa4c07e0683c530b4aedf1033d6d447549023892ead37d0b6fa532dee0b178ac40c7bc73f766c03fd16dac196792323459b5b73129d7b826bbaf219f67df20417370dd7dde072e8b8af1acdbf11134b50a17b32c69627c601f49733dd82d6da7b121db6f267607850dada4c79683f8de8649e54c209dbe2d3125ef211d625d02ea6a5553454f92131cb9359b17333e2591bb72ad09bce32b876913b0b061e98d85e62333ab1e32df954cebb267d11d51a10dff0cc9de91cc4d569d6526b1361abb681d92f6ede1a25c46a000ca8111b98ab2bcd6e947fe4a7622d8dbef93119274ad79769fec0df6736374d3de291f6abfd7c597aa8393545250de65efc29a95d32770fa5c61705a8357eccfc75033aa2cf98a34c8246cb4c0f39c2ff86b2a7b98c9fc45a9a7c8f3c45fd37e8467c29fb6de11f1b99e512bf361e7359b3c2d2f690e0bb701b00d3d9aa083e627a624974fae6a01ce354709c27e051ad5d5e3404b62e1254841b1f70f7fbff580e364908a7580b4f76a10e1f793060a23ace5326135376670d7208fc3bc2858375d66125adca07e547ad1ca2f8b6046a76d1c2a1dcd5d31a402e2efbffafcf11e79f2b34fb8fc6d7cd66b03f08bece054355d2ab6eae7cd19ed763e9c08f087e5d1937e771f76dd59388be4002c7338de18f4afa47f1a4d33aaa65359c0f5b706550db44684feb71915f1c34e143d03794ff1a60072de5690bb87b2618b90b19d79e9be54d16928497b0b44355b0b5f33212f620df0a03714220a0f3e51172349a00dd9a7ff0fbdaea71366ed64a0d7eb5c15d4e45e73a42e955a54c25f2886c54ecb60e122786d8041198761ec20ecad4e97502b450bb14338d827dbdc55b57b00c07a6c58c8ef5e34753b7cb59327f1164137c6b9f22d86a5f21e638a3a8cc8b45652557883c643536ef3d9d19b491ffdd37025b0f96f10305a00bc009234f4403accf3de137c3b01347a232f717fbaae5bc9fc93d67f2d7037eeca7fafe613b7b7b7066b25836c8a866320f18b87d94d3299672876f393f52720ab1348d354fb6f8c6d1e712c2edab59cbf30f18c280593a9331596381fc2bbfbdf6ddb7b16bb3f9a529de22498d3185274cd2bad4e604fb4eede695638ca7cf169500dc594f6044c5fa59ea7fe76a4cbc4ad06accedc3fc5ff1d39176374bd22ad464f2514bae32550bd5a5565754047b5acf42d6e2fdba27608c452b66018ed190bc1cf6fafaa1d3d043a09582265922249226e028e7b1d0de65405926b3fcbf767143f90921f6462c18615ea24f741a9d595aac67bda8cc7ffb9e342f4349a8f1b93e71d35bbf5c06b975b830ff8589bf39748e5104b17564eefcde29fe0805cd32719e40431773fb66fc8271106ad4afbf60fce825de6a1d11402f546925f1008d60b6f9e555b987edba01e4f30e568e4a461e7202b02cdcd6a9eeb4f454b7d6d0168305c4018481ce0e8ed0075fed312a0edd95ec85aa0744b6b454ed067a61acccfdff49bf82218ad2b30df4ea8ccdc6020f1001e08a5e254a5337d1b031ae91bfb24774509ea26f06d2746f3163d3b23cdcc7ed69b2cfb449688de9d68040c50751d0a01a2b6010aca6cf4f5fc843687e250a0fde94be03ef78633a90548ea9c0fe7fcaa4402d2694ba76c58429119f6962c75f8b0182d7522fd1db5d966e443b781eb8727b007c599a4d60a07af05f92dc8b7a36d635169765df58ccb5f7a4ec76cb015f834e0ed5db3991a83f583d632d6f8cb3ff52c998ef7c9b48c9e0422ca906b07d50f3afe36801684b5cfd3b31dad337c0acb88d55ab0afd5e4868d8bf3edb49b1c8d2c93759ae6f872608b00f2a5cc4b5ed0729ca72c6f2f8aea5b31d8c6a8595e98c4bcc8401a733001662fffab00ea260afd56b819ccc5bff75ba20a7e5c7323428ca427cfd9010c97bb3332052198b8f5c0f4e803156743f3ffaeb8d071da31e40cb2211143ced9ad859483bad34d1723930ca2538509455d2e548289b05dd63c2d877e35baf892f5908837cdf69bccc4c4bd2e37a9a4b57d224cd8bb259683ab40333861151d7a277cf71b2aa28d2d843201ab6cfd0168f5f44f54d103c5bca8d446ca40efdb467577469597fec6c989686f1759ae2c046ca3d174528536ae9de80e975eb3b428ed7ff9bbf6ce75d85f5821839115468517f85d572a5bf5941c02b9269ac7fdf8e87f582898bd85ff097cd475ae32b88c85932b5447eac8340098ce266bc3dbd9912382dcc158e2dc1a3433ae95df3ca94432d608067f8a7dc6de153270342ba2e467bbd663577a160e0f3b5101442d9fae394a6517c2b326e381e82378af8371cdaa365b31ada5984e857fa5d12babb35fbe184b27d79e62dd568b76896a0c26f0ad7319bf9636406b10d00846ab23dcc8cda92c50dd630ac011b7c71e766ae3f82738b0239715cb2e8b0714237b529bfcbb5aab66720a6d2ea3d37eb9d1b6f3ed619eebc1f2fc171087de3ae3e629ece814118bed3e648aec9cae898f95ac4828542bdd1e072b648482b6255e655333947515548104cd3df0ff5505bc74d86ff26092c7bafd2a3be1fc4824cfe4e2d903c80010af37c95dec06ba4255180fdc937262a3b8d5bbfa4d71e1b8c56da8cfa5dd024b70f086f7a002c502ebd9e03aa75a7fda24356cc123fe744c717a3dd657f8a3561b916ae90b2b103826b14655ffeff0911cc01c131dc88cc5f6e16a7357096736526002246d9566d704ff127a683037245cb03aa26c6758d60b65914fc725e18e0679b6fac8c42157c291d4b1c57580a9e3afa9184e33fa9c3aa195fdd5acfc72b2cd36da62938f3f6598069a8ea1f4941e6757b5021393b1c52e2d4f36b35794ae412b960f6fc300b0e5ccf9c55abb08fa9b6897e65bdb391b4a98389e58f6cbe79410e196c5940e61f9027deef77e0aeebbf28775656b0d235953dab96909c32eeadc3ec61d499ba6aeb3500cef23ab63830f67ec1c07ca5310cffab39ddc9d398ea45f0d50c58f1fd260342e1521ba3184d7e0a8681ade789f4233e80e1d197be272e382ca5daf9f84e8fb1b1b5581a3c326ebdaa1b5df2bd798cda6dea386033de9f1024e910243da9c1be2fab7baebd1de907a8b8fd14fda621dc57f14e278094f577dab7e1e2fc3295088f7396e7665052cae8cb233f47e7b389feda234d44a8c13cc60a30f5541b2d08e173104dc97e44869323bfdc8190e30d94a2fcdf249f3ec78e8ce1b683908df37c6e5c9c47a6bd02037fd201a8577d4f19e5b3488e82fbaa090e9f7e992ce56b02dccbb4ee887fe3504617d125b0f80c66891dd8652097928cd1f66a44f54ff803b7b6d44da01bd5c5298c3b8bc6ead2235e7b2f72b6e4d335a4c8e347c40def417ba64257a879d6a4617c94e22ce9c4f21a95df398b7bdcb7e3c83fe7c0a8f271bbaa2c2606d92a6f3bf7991569a50ce614ed73a86dc7f362308899e325aab00d06a975066f0506a3b30046981d0941f65e17e05c3283d0b5ed6633a705ed90a221cbc892fc5572288183ea006bc83c48fdbe31f23acd3aa55207e7d583f74349cb6609e7849802443b4834fa3fee278020dc40f56c819a21696427905de90d8bde73f31933caf66871aabc6e375aba4e496a7d216d3e6b449f68f2c5c07ce5ebd2c61eef95e7e05d15a8317a831b12666de016eab708c89023223c7f5bb456b1afa758b820e26975a6c16de1fe1eff5ad4786ccdd808601ffa23f59499c8bca5bfd14427c36bd365001134dede46bade845cbc47886e14aebe2fd18d5586a53447c3f205ac4826dc8dba74f5ea47d68675bd31d6d9e3f53663a7aecc26830e91550f4d13295e03e339945bb8482f5d711f17d627f820e7885d909d87bd0a8469373c9b143ed1d6d6f3d9ce392fb2616766c704d730df0635d21670e4dadffdf71105bc0862e24edfd61a21d3c7db4af17feb4f3cdbaae80f10819974cd8d88b3e7ab7426b9d3e0b406c5164386319b992eb176cd92985dbc36bb9410283861bb6a8e0d19112c12caf6a022437bf0cb1535c5ddfe2dc568bc4e62848476a2ac58f539853687be953afbe386cdd05056e2c03fd24734329dcc770b267a533e6c89e268586bcf3d566085e8ff52cfdd55381b7b2c3ef912f505f1f3bc22f77bea575cce54b4a448d289fc5dc41523001aee5670fc33d60dae1d2c3091c55dcd53b73d09e55ec92da41821c2b489b210517b9a7c5e25896def7935bb8b9829b6ef69a2c089406d9dd37ddb81cd1132c174c75158efb2942080c258da1f8fa51d0b5ab5d65321f6313ce10bef5cdafbf8f11b3e665dd24fe6bd5237a9bc0b192008211fe0d84b39ef6334d239bca8d9aa542a64d45ee2ca621baa21550b748e6df9cd5d774038ad340b842ea350ff59b84e6064ea3ed243d20efc70c34dddd863ec86cae1a20b1aefbcd114e0ca4cf463c23703e20d29a040c6027296bf86d66b663f8056ccf729b60f9ba0c07b59d792cc835af2780b62e57aa6c68cb66647f917b00480cd319ef5724ebc2d520398d2100f6821a801321fedf7f5f8a77026ee08d67c1a9f0b0604e0df82b5c0a7d8831dd59e2a708c61a6dcd61cccf25d909f652b14165723f54afceeabb843bd274c479c29752ebcc7d8e169ea64cc8276f17d5d0781d9312d36c40351fb01488c90b3252033be204a88fcb9da8588a45e6fa3143977b620dc5809425603e8536ef99fa3363fa1ff71c4a9d44fd49a8740ca5d1276033a3c0138e36bb1b1e3da927ad76715b36b77ae531de979854f27b1aa75eb3c57f0f7588a78efd7ffba0ca32691f1bd14a8214e6991b140829627cfeb48e4bca471514c3ad197058dc0e82efefd3f19602f11abfa14694c36681a70443d12a482f5312a3f11ebce4d91a8f9cea23e727f2c7dac9cb9fd937e9c4a529de0eac81de3f361eb4884d45df578010f8c905e1f375c80db37e11d6bf084e53ec4e10c7d6ec257933b3910b1a370fef6ede3a692daa1033171e485980227e24a0233d4bfc297d214f63e10b98c1ad8296944a6119f1c19e9b325e33ba33bbf617869720c9309f9d72661a00677c043877ebb90514cc45dbd9d874174ae4cc4b8c4b6d20f72d712c4da6f70fff7073b8742a25866964a1a10388ca8039697019c78b1f0d508dfb2584be729562e449ad3f0640b3d10631e7214196dd9d1164d7cbae378076c670f86e78612bb71412971311f48c73f376ab7da9b8b6e6d17590be6ab3161288e889252f75c9d658ed40803f96228b6213c6ac9e9b922e92069974dbcf3925da8d7098cc23a239ac6af14a3897fd7c58faba25cb2fdc667ec6539655e35477b2d9b7cc5feaa6cc71c05e1e19d3a84cc26e754843686fe4135d78cb6ab9035c47c2c2005261fee668818d8c19110e211bd77de66cb90e39e5beba9a30d90dd7cd799290db4e4574a34eb5f1cddd079107c8fd14d53c7010c5db39b6a5498b58b1895f716bded3427c38828b6b5fe733855b84ca91ad8323541ee6ee57d56f393c490516a380a382f9cafc561a6ead8c1b037225b53f9df7b9a80f789e175a4731ea8e62c4d1eba99c5dda16152822a6ed22437c8ae5278ad039a35cd5b21026e0834b6770581fd71d23817c772c1b7a258d5ba414848cc25c31fc712d72517dbc8d83e3ac75cdc17f1da427d8a3aa394633ce87b2bb1741f0fcb7c2c89b2496b04dfde9193af1380561cf57af97ddccdefa625ce6e156cef618b31efe9fdb9b1977d91ede30e0c25d568db96c0500e0c29b8345163a181a28d6979af11a23a625c4e3f3122d605a895ee51fe6174e38e0c1c5928e7fc91d1ba3491dfeeba10c473c93c7167067485216a727fcfaf788dfdff54aaa195bcdfaf20ce328a8cdbec7036b82afc256289e59b828ae287c42f97f961edf0adcc303dc702f1522bbbf56de9ed0f14af58a6b1335cee3af19da0e09bb5cd50c981520501958c2053a396befc921938854c0c25d02f24b94e43b307fa97c6b50927bfc539c1289164737d7297343ab0d8351f4c1ff88369a6188ef2fddd791e2b1e5137f0e2a6caa7d343f909b1f14a6d838b8ec54d9ca6efd4c94204fdd212b5629cdcb0b1da0ac1be611616d92d67c1332e0dbc188f15e824aa3d588d31952412b3d33d94fdb2d24c4d01b74f00d6cf97effd336a4d064b22f54f304a70272270740e254dd3a6676f46d10b09b704ed985f6bc03ca67088d258a0a2cef42baa93d70a3c1e0ad67eda6455c0acbe0d83ecc06571c86802d0221546b1908d223de306172393339c2f31e7178f56573d461d38f89127ffd6fa8bf8eb5af17d441a3b73719ac961c90c758aba2a40794cc8622fc20f33568464ebb8a46279dc22b7558813633d517a7859fa199ea4c0925149d6207c51d7ed8db4020ad2f8ec8827973016a7ed4f7421e0430465ca023d2475a7f011ca303d6f50ca545c36a0d661a0d791735df98a8c0be6d2f5f3e45aaab847976e8d6d1e8d6d8fdef5a39673fcce748b38c038b6e45520be28c361988f6b84fc05a0237baf6c0be917d10ed9b4aa5d6ee30f3fdb013b9ed885d3a416349b9aa0055c0b72b74d34598484ffade6ce99576677d15c9963295096f3009346f159974508c0bbbf97a0b49e301a7244f66a7fc5db776e468658dc4415b045cacc98670f05557fab0128b154d4e2e83038183e571ade7e2bfd0c7094975fff8b65a41caee5e426bc85e8691b0aa40b8f683d02bb09cb491050ceff47d5d189c6250427fc2f3bda870a1a29bcf7e56e655b476abd575de8645d68ab48152a46787617def65efacf27054c8fbc590c4e210c7b3897b3aeb7edfa18cbb9c99ebd4626adab5cdbcb842722b775a3645d4dba8b502979c7a470dbf44efbc76d126eda10ac4baa073b35bb3f1d66c16483c18c21105d7b4653dfa4e9231e04c18878e1744d5b05bd243a6ce30159e279fba1a28aa860372104420430d7b21f45a53150c36af535206608e06f4531d34e8c2c27c7c7e98bd0bac78f0e76f713f9755dbc3f41dbf9e619b7ce4e23d1008c5503f453794bd08bb1712bd60123d07a2b00b24b07bc0a39039586de382ff1f506432c792178f983f1a09ab8f3a2198204bbe25f2bce6a024c914572a66a0a8713cabdeba17c3bdb037f111ae4f6ff904da48398825c8b89783634911c964599062928cad7e66ad39542e526874bb54fd98e404d4f1b153d5dd44e3a24f3f736ed9bed13e247be609b045b313de0129211effbe450d2830e0e634ac3d3e54be181b76120fb44086b3cf31404b0f8687700b4b148a37045ff0a0ad649ef402797bb1c8ad7dcceff056959ddf84d08bd27a5c25c21f2f2a79adb248dce4bf3c69873cd3523f687805d950f09ea3f2aa5c863650de62a3824b9480ee0b36dc521c4e4b3d2d2275e0fc48b9bbfc990bc2adf1ed609aaeca8c89b7f42d9e292868adbae5efd6bf93ed398438e8f96ce8b9394b4e7baf069cae7143876d31abc42c913a23d79ecdccc58c36b2385938fd34798b2323c608430bf652a00a9f5a942b1d302b4539fb229cf22d55ebbbe5238b0397c69e4d837b93f463cc044bf0e05f1f966e238bc1dbc529922dcca64a54b6eab6f9a22c086a2586767e1a9f2744bb2a23933405dbc5eff612ce4dc9099477d0a8602968410ce9edc8f0a96b339c4d998eb2e81df7fa711c3f560dfce772a80f9c7949435f87e35808ee7a9b7cc39e990ea21437eae16fd77c93d6e64d3bb1dba354fd3512ec4f86e7e967b70442108ed4c63d60de78fa2bb5be6aa3a38e58e5479852612369244fe219725a1d9cb0f104c690c0a8bb831035998394b703cdaa91e4bc2d739923db11b2452ed7d06835f309ea4a0d5c825a34c512a0fd412302d39421b1d61c37a4fd7b5d8107bf59432cd6253735f7ad74f2de1f462d12245a984588354fc0902f3c38925b87edbbf7be28d5b7c3c2e7dbc94fe48a2fefbc420b142b6bc850bd7c1495404e023629e574c5014fc2b11f78ddf963226f2e82aed2b91ae436c2d72125886c1137bd6fe775b3666a5b92620f95938c66894e43b04a97a3310a673b2d6ffa8066c6c1cca0f4f71bc322595b85c42e55e869c1b72fc9414d42a7c7631b8b24db104ebbf1e38264877999e2739ddd44c3954a29f33917172b09bc480667e23d626eca8db6bd5a7cc073ba7090455fa74c7bfb1bb1953ba9a153918d2ede37ffd582ca020eb9a4d7b6e5c3a2bf4cd38f66c2a5bc56fa77c7e5e7cfcbdff82ebe92c0a85b8d7a8e911bfd7fae3c46b75c44de2555218c7a45857220779a15d72f73b7bb73d3bece13769fc5c9370395a05b544ad905e9c2dbc9c8cbba9c2dba94815505932d56427eee2b868b050044bedc72c89812962a8572273d01298bbad79a5262b46961da2fa62672bc6dd8c0fae648a53949c4fe6b29fba4a617af8c9a61acba94628790231475701644f44b8281489ce6a369d600880cfc354757bb8ddfa3bdb49b663d2f74c73e4e45725e7cf39c4a1c1f5201881875756595a9da39abd5b2d249f3f6e8112483e0837ae225cbcbd45b2024a0d60502fe51c3c750e6d6bf75026dd1c36bdb2a75053631dde567621e3cf557b350a255e12af5539b71643c699d26a7872f47303fe53eecf098b20d15847fcdeb9a21a5e0ef43565bb28c5f4d9edb1cced5f9ef296d543b88eba292ba3dc3f6068ed68cddcdb2f7e87419dce79be11eb3e17c8433068e7749f6456fb9f2401e1aa8f47d590baa42e73f9df977daf6f66c7f498722b894137a5c1f7782c4c5c2e35abfc2454bb41d18f010ee5ac6cac86424fd4636435d289b20b0ee8d2cbc3eed84ec76eac266796c5d27ee48cf48d0b366cdee89a5c8191adcd3888e723ef189fbd1f337cc3cacc0ed45f9dd2076b387ae67e480ad94c757fc6b4a3763a10baf134a8238bd70874d16693caee3458a6390420672817bb474ebe63c0603a99f83bbdeca2be44d3dec06b72ef083a062b249432e0c14f6a8fb70675c8ebbd10d7ff6362cb6ade170099dbac7c148acfbaafd61943694f278f5f37576a7271c0bf6bc91db779a6595bebaf3a73a7c8231101ad7513c2437874f3eaa52c8ae1601f74c17a4164cebe96707f2d51255e98bbeed987cbe39809bd82d239ae05e0804b8b649cf062f1595bdaa4f3a22e697a4102f707ce750b3fa3cd10c0815fe512e7c9efdaf712d6a84e63fb47d53040d73b8bee5032e31e898b644119337df5b99a1159062efacfb1347a49f253a4b0a2de8b19000ede20913ad3c26e0b6d057a07d117c77d7c6b979830ce10e4e8a0ed5dd3c914b30a336df4557bfd7fc8de16130c82530235754efd7883a3637859bd97a920f2fc3bd21aa00a4611b3bd5a0283197e549db3f26811657f6c3d5f0e6fd95b2c0b6907764a7a7bd9247dc3024afbf308581e09e3a9722bc5c717a69f419d50d97fa12aedc5ad0f602d72da6aa3a1733564b180c0c2b7990255d21f8fa826f72568544dd3afb0173b837d6ecacd440a5a416767d20655fae69439b5ee8fa36df1d1297361f73f813eb80cb7afdeb193169c2fa961deadd26ddb90d0351a23d1f3ef089fd4e7d4003679c570c64926827f055d78ef8b6e73013cecea119029a3a15dcb3ccf742e82f43949756d04760cd164b79726dcd68570e088dd130da69bb1c560ed4c733e47b28aff2b6121a0760fa1086aa5f2b63481cf2c639ca8bfdc14bab75fa6780521552a9ad31615919c691438ba9133e49a87cf609539bbd8c4cf621cdf0a1a7e80d39688c4d70926e092642cfd2bbfc68ac5035a283da481741d6cbc1b9d079b56a76f11b78ab4f119994d6a1071d18ae8a4f2e929d3fe5e9f15a1cfdf7451260124c83f4a1731d00314ba8689e4b4e6f334e29d2ef3d702d28e563e4436e6b038d5944fd5bba37098b12017efd137c01ee7b587eca1b45f263efa8adbce970662f1fbde165349200432ece0f9c59abc5099b53a292ce77fa1b3ad86b2a9da6bff484654b80aba151e82f5ff4c2799cbe8dda1b1a851b79ab984fdffedf16a83165a1cd3eac5f601cfbb1060a8175ac9f0cf17b8fc5bf982db7c3ffc4fd3b6d51359c06a2f8cac4e9c79631a9df261b65a651ca47d5a6572c0c2957f28a21d5ccf86498588bcf820a7d761e9bc0775e06e88dccbe8d4a8f0b8dda74c78aca2d1decd39e18e7f5d93446e82608096358b4a40a9\n \n \n \n \n 您好, 这里需要密码.\n \n \n \n \n \n \n \n\n","categories":["干货"],"tags":["Interview"]},{"title":"acwing基础算法(1):基础算法","url":"/2022/02/22/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/L1-%E5%9F%BA%E7%A1%80%E7%AE%97%E6%B3%95/","content":"快速排序\nAcWing 785. 快速排序\n\n#include<iostream>using namespace std;const int N = 1e6+10;int q[N];void quick_sort(int q[], int l, int r){ if(l>=r) return; int i = l - 1, j = r + 1, x = q[l + r >> 1]; while(i < j){ do i++; while(q[i] < x); do j--; while(q[j] > x); if(i<j) swap(q[i], q[j]); } quick_sort(q, l, j); quick_sort(q, j + 1, r);}int main(){ int n; scanf(\"%d\", &n); for(int i=0;i<n;i++) scanf(\"%d\", &q[i]); quick_sort(q, 0, n-1); for(int i=0;i<n;i++) printf(\"%d \", q[i]);}\n\nAcWing 786. 第k个数\n\n#include<iostream>using namespace std;const int N = 1e6 + 10;int q[N];void quick_sort(int q[], int l, int r){ if(l >=r) return; int i = l-1, j = r + 1, x = q[l + r>>1]; while(i<j){ do i++; while(q[i] < x); do j--; while(q[j] > x); if(i<j) swap(q[i], q[j]); } quick_sort(q, l, j), quick_sort(q, j + 1, r);}int main(){ int n,k; scanf(\"%d%d\", &n, &k); for(int i = 0; i < n; i ++ ) scanf(\"%d\", &q[i]); quick_sort(q, 0, n-1); printf(\"%d\", q[k-1]); return 0;}\n归并排序\nAcWing 787. 归并排序 \n\n#include<iostream>using namespace std;const int N = 1e6+10;int q[N], tmp[N];void merge_sort(int q[], int l, int r){ if(l >=r) return; int mid = l+r>>1; merge_sort(q, l, mid); merge_sort(q, mid+1, r); int k=0, i=l, j=mid+1; while(i<=mid && j<=r){ if(q[i] <= q[j]) tmp[k++] = q[i++]; else tmp[k++] = q[j++]; } while(i<=mid) tmp[k++] = q[i++]; while(j<=r) tmp[k++] = q[j++]; for(int i=l, j=0;i<=r;i++,j++) q[i] = tmp[j];}int main(){ int n; scanf(\"%d\", &n); for(int i=0;i<n;i++) scanf(\"%d\", &q[i]); merge_sort(q, 0, n-1); for(int i=0;i<n;i++) printf(\"%d \", q[i]); return 0;}\n\nAcWing 788. 逆序对的数量\n\n#include<iostream>using namespace std;const int N = 1e6+10;int n;int q[N], tmp[N];typedef long long LL;LL merge_sort(int l, int r){ if(l>=r) return 0; int mid = l+r>>1; LL res = merge_sort(l, mid) + merge_sort(mid+1, r); int k=0, i=l,j=mid+1; while(i<=mid && j<=r){ if(q[i]<=q[j]) tmp[k++] = q[i++]; else{ tmp[k++] = q[j++]; res += mid - i + 1; } } while(i<=mid) tmp[k++] = q[i++]; while(j<=r) tmp[k++] = q[j++]; for(int i=l, j=0;i<=r;i++,j++) q[i] = tmp[j]; return res;}int main(){ cin >> n; for(int i=0;i<n;i++) cin>>q[i]; cout << merge_sort(0, n-1) << endl; return 0;}\n二分\nAcWing 789. 数的范围 \n\n#include<iostream>using namespace std;const int N=1e6+10;int q[N];int main(){ int n, m; scanf(\"%d%d\", &n, &m); for(int i=0;i<n;i++) cin >> q[i]; while(m--){ int x; cin >> x; int l = 0, r = n - 1; while(l < r){ int mid = l + r >> 1; if(q[mid] >= x) r = mid; else l = mid + 1; } if(q[l] != x) cout << \"-1\" << \" \"; else cout << l << \" \"; l = 0, r = n - 1; while(l < r){ int mid = l + r + 1 >> 1; if(q[mid] <= x) l = mid; else r = mid - 1; } if(q[r] != x) cout << \"-1\" << endl; else cout << l << endl; } return 0;}\n\nAcWing 790. 数的三次方根\n\n#include<iostream>using namespace std;int main(){ double n; cin >> n; double l = -10000, r = 10000; while(r - l > 1e-8){ double mid = (l + r) / 2 ; if(mid * mid * mid >= n) r = mid; else l = mid; } printf(\"%.6f\", l); return 0;}\n高精度\nAcWing 791. 高精度加法 \n\n#include<iostream>#include<vector>using namespace std;vector<int> add(vector<int>&A, vector<int>&B){ vector<int>C; int t = 0; for(int i = 0; i < A.size() || i < B.size(); i++){ if(i < A.size()) t += A[i]; if(i < B.size()) t += B[i]; C.push_back(t % 10); t /= 10; } if(t) C.push_back(t); return C;}int main(){ string a, b; cin >> a >> b; vector<int>A,B; for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0'); for(int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0'); vector<int> C = add(A, B); for(int i = C.size() - 1; i >= 0; i--) printf(\"%d\", C[i]); return 0;}\n\nAcWing 792. 高精度减法 \n\n#include<iostream>#include<vector>using namespace std;// A 是否大于 Bbool cmp(vector<int>&A, vector<int>&B){ if(A.size() != B.size()) return A.size() > B.size(); for(int i = A.size() - 1; i >= 0; i--){ if(A[i] != B[i]) return A[i] > B[i]; } return true;}vector<int> sub(vector<int>&A, vector<int>&B){ vector<int> C; int t = 0; for(int i = 0; i < A.size(); i++){ t = A[i] - t; if(i < B.size()) t -= B[i]; C.push_back((t + 10) % 10); if(t < 0) t = 1; else t = 0; } //删除先导0 while(C.size() > 1 && C.back() == 0) C.pop_back(); return C;}int main(){ string a, b; cin >> a >> b; vector<int>A,B; for(int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0'); for(int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0'); if(cmp(A, B)){ vector<int> C = sub(A, B); for(int i = C.size() - 1; i >= 0; i--) printf(\"%d\", C[i]); }else{ vector<int> C = sub(B, A); printf(\"-\"); for(int i = C.size() - 1; i >= 0; i--) printf(\"%d\", C[i]); } return 0;}\n\nAcWing 793. 高精度乘法\n\n//高精度乘法#include<iostream>#include<vector>using namespace std;vector<int> mul(vector<int>&A, int b){ vector<int>C; int t = 0; for(int i = 0;i<A.size();i++){ t += A[i] * b; C.push_back(t % 10); t /= 10; } if(t) C.push_back(t); // 删除前导0 while(C.size() > 1 && C.back() == 0) C.pop_back(); return C;}int main(){ string a; int B; cin >> a >> B; vector<int> A; for(int i = a.size()-1;i>=0;i--) A.push_back(a[i] - '0'); vector<int> C = mul(A, B); for(int i = C.size()-1;i>=0;i--) cout << C[i]; }\n\nAcWing 794. 高精度除法\n\n#include<iostream>#include<algorithm>using namespace std;vector<int> div(vector<int>&A, int b, int &r){ vector<int> C; for(int i = A.size()-1; i>=0; i--){ r = r * 10 + A[i]; // cout << \"r: \" << r << endl; C.push_back(r / b); r %= b; } // for(auto x:C) cout << x; reverse(C.begin(), C.end()); //删除前导0 while(C.size() > 1 && C.back() == 0) C.pop_back(); return C;}int main(){ string a; int b; cin >> a >> b; vector<int> A; for(int i = a.size()-1; i >= 0; i--) A.push_back(a[i] - '0'); int r = 0; vector<int> C = div(A, b, r); for(int i = C.size()-1; i >= 0; i--) cout << C[i]; cout << endl << r; return 0;}\n前缀和与差分\nAcWing 795. 前缀和\n#include<iostream>using namespace std;const int N = 1e6+10;int a[N], s[N];int main(){ int n, m; scanf(\"%d%d\", &n, &m); for(int i = 1; i <= n; i++) cin >> a[i]; for(int i = 1; i <= n; i++) s[i] = s[i-1] + a[i]; while(m--){ int l, r; scanf(\"%d%d\", &l, &r); cout << s[r] - s[l-1] << endl; } return 0;}\n\n\n\nAcWing 796. 子矩阵的和\n\n#include<iostream>using namespace std;const int N = 1010;int a[N][N], s[N][N];int n,m,q;int main(){ cin >> n >> m >> q; for(int i = 1;i<=n;i++) for(int j = 1;j<=m;j++) cin >> a[i][j], s[i][j] = a[i][j] + s[i-1][j] + s[i][j-1] - s[i-1][j-1]; while(q--){ int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; cout << s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1] << endl;; } return 0;}\n\nAcWing 797. 差分\n\n#include<iostream>using namespace std;const int N = 100010;int a[N], b[N];int n, m ;void insert(int l, int r, int c){ b[l] += c; b[r + 1] -= c;}int main(){ cin >> n >> m; for(int i = 1; i <= n; i++) cin >> a[i]; for(int i = 1; i <= n; i++) insert(i, i, a[i]); while(m--){ int l, r, c; cin >> l >> r >> c; insert(l, r, c); } for(int i = 1; i <= n;i++ ) a[i] = a[i-1] + b[i], cout << a[i] << \" \"; }\n\nAcWing 798. 差分矩阵\n\n#include<iostream>using namespace std;const int N = 1010;int a[N][N], b[N][N];int n, m, q;void insert(int x1, int y1, int x2, int y2, int c){ b[x1][y1] += c; b[x1][y2 + 1] -= c; b[x2 + 1][y1] -= c; b[x2 + 1][y2 + 1] += c;}int main(){ cin >> n >> m >> q; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) cin >> a[i][j]; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) insert(i, j, i, j, a[i][j]); while(q--){ int x1, y1, x2, y2, c; cin >> x1 >> y1 >> x2 >> y2 >> c; insert(x1, y1, x2, y2, c); } for(int i = 1; i<= n; i++){ for(int j = 1;j <= m; j++){ a[i][j] = b[i][j] + a[i-1][j] + a[i][j-1] - a[i-1][j-1]; cout << a[i][j] << \" \"; } cout << endl; } return 0;}\n双指针算法\nAcWing 799. 最长连续不重复子序列\n\n#include<iostream>using namespace std;const int N = 100010;int a[N], s[N];int n;int main(){ cin >> n; for(int i = 0; i<n; i++) cin >> a[i]; int res = 0; for(int i = 0, j = 0; i < n; i ++){ s[a[i]]++; while(s[a[i]] > 1){ s[a[j]]--; j++; } res = max(res, i - j + 1); } cout << res << endl; return 0;}\n\nAcWing 800. 数组元素的目标和 \n\n#include<iostream>using namespace std;const int N = 100010;int a[N], b[N];int n, m, x;int main(){ cin >> n >> m >> x; for(int i = 0;i<n;i++) cin >> a[i]; for(int i = 0;i<m;i++) cin >> b[i]; //双指针 for(int i=0, j=m-1;i<n;i++){ while(j >=0 && a[i]+b[j] > x) j--; if(a[i] + b[j] == x){ cout << i << \" \" << j << endl; break; } } return 0;}\n\nAcWing 2816. 判断子序列\n\n#include<iostream>using namespace std;const int N = 100010;int A[N], B[N];int n, m;int main(){ cin >> n >> m; for(int i=0;i<n;i++) cin >> A[i]; for(int i=0;i<m;i++) cin >> B[i]; // int i = 0; // for(int j = 0;j<m;j++){ // if(i<n && A[i] == B[j]) i++; // } // if(i == n) cout << \"Yes\" << endl; // else cout << \"No\" << endl; int i, j=0; for(i=0;i<n;i++){ while(j < m && A[i] != B[j]) j++; if(j == m) break; else j++; } if(i == n) puts(\"Yes\"); else puts(\"No\"); return 0;}\n位运算\nAcWing 801. 二进制中1的个数\n\n#include<iostream>using namespace std;const int N = 100010;int a[N], res[N];int lowbit(int &x){ return x&-x;}int main(){ int n; cin >> n; for(int i = 0;i < n; i++) cin >> a[i]; for(int i=0;i<n;i++){ int res = 0; while(a[i]) a[i] -= lowbit(a[i]), res++; cout << res << \" \"; } cout << endl; return 0;}\n离散化\nAcWing 802. 区间和\n\n#include <iostream>#include <vector>#include <algorithm>using namespace std;const int N = 300010;int a[N], s[N];typedef pair<int, int> PII;vector<int> alls;vector<PII> adds, quires;int find(int x){ int l = 0, r = alls.size() - 1; while (l < r){ int mid = l + r >> 1; if (alls[mid] >= x) r = mid; else l = mid + 1; } return l + 1;}int main(){ int n, m; cin >> n >> m; for (int i = 0; i < n; i ++ ){ int x, c; cin >> x >> c; alls.push_back(x); adds.push_back({x, c}); } for (int i = 0; i < m; i ++ ){ int l, r; cin >> l >> r; quires.push_back({l, r}); alls.push_back(l); alls.push_back(r); } // 去重 sort(alls.begin(), alls.end()); alls.erase(unique(alls.begin(), alls.end()), alls.end()); for (auto item : adds){ int x = find(item.first); a[x] += item.second; } for (int i = 1; i <= alls.size(); i ++ ) s[i] = s[i - 1] + a[i]; for (auto item : quires){ int l = find(item.first); int r = find(item.second); cout << s[r] - s[l - 1] << endl; } return 0;}\n区间合并\nAcWing 803. 区间合并\n\n#include<iostream>#include<vector>#include<algorithm>using namespace std;typedef pair<int,int> PII;const int N = 100010;int n;int main(){ cin >> n; vector<PII> segs; vector<PII> res; while(n--){ int l, r; cin >> l >> r; segs.push_back({l,r}); } sort(segs.begin(), segs.end()); int st = -2e9, ed = -2e9; for(auto seg : segs){ if(ed < seg.first){ if(st!=-2e9) res.push_back({st, ed}); st = seg.first, ed = seg.second; } else ed = max(ed, seg.second); } if(st!=2e9) res.push_back({st, ed}); cout << res.size() << endl; return 0;}\n","categories":["算法与数据结构"],"tags":["acwing","算法模板题"]},{"title":"acwing基础算法(2):数据结构","url":"/2022/02/22/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/L2-%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/","content":"单链表\nAcWing 826. 单链表\n\n#include<iostream>using namespace std;const int N = 100010;int e[N], ne[N], head, idx;void init(){ head = -1; idx = 0;}void add_head(int x){ e[idx] = x, ne[idx] = head, head = idx ++;}void insert(int k, int x){ e[idx] = x; ne[idx] = ne[k]; ne[k] = idx++;}void remove(int k){ ne[k] = ne[ne[k]];}int main(){ init(); int m; cin >> m; while(m --){ char op; int k, x; cin >> op; if(op == 'H'){ cin >> x; add_head(x); } if(op == 'I'){ cin >> k >> x; insert(k-1, x); } if(op == 'D'){ cin >> k; if(!k) head = ne[head]; else remove(k-1); } } for(int i=head; i!=-1;i=ne[i]) cout << e[i] << ' '; return 0;}\n双链表\nAcWing 827. 双链表\n\n#include<iostream>using namespace std;const int N = 100010;int e[N], l[N], r[N], idx;void insert(int k, int x){ // k的右侧插入x e[idx] = x; l[idx] = k, r[idx] = r[k]; l[r[k]] = idx, r[k] = idx++;}void remove(int k){ l[r[k]] = l[k]; r[l[k]] = r[k];}int main(){ r[0] = 1, l[1] = 0; idx = 2; int m; cin >> m; while(m--){ string op; int k, x; cin >> op; if(op == \"L\"){ cin >> x; insert(0, x); } if(op == \"R\"){ cin >> x; insert(l[1], x); } if(op == \"D\"){ cin >> k; remove(k + 1); } if(op == \"IL\"){ cin >> k >> x; insert(l[k + 1], x); } if(op == \"IR\"){ cin >> k >> x; insert(k + 1, x); } } for(int i = r[0]; i != 1; i = r[i]){ // cout << i << ' '; cout << e[i] << ' '; // break; } cout << endl; return 0;}\n栈\nAcWing 828. 模拟栈 \n\n#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 100010;int stk[N], tt=0;int main(){ int m; cin >> m; while (m -- ){ string op; int x; cin >> op; if(op == \"push\"){ cin >> x; stk[++tt] = x; } if(op == \"pop\"){ tt--; } if(op == \"empty\"){ if(tt > 0) cout << \"NO\" << endl; else cout << \"YES\" << endl; } if(op == \"query\"){ cout << stk[tt] << endl; } } return 0;}\n\nAcWing 3302. 表达式求值 (不会写)\n\n队列\nAcWing 829. 模拟队列\n\n#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 100010;int q[N], hh=0, tt=-1;int main(){ int m; cin >> m; while (m -- ){ string op; int x; cin >> op; if(op == \"push\"){ cin >> x; q[++tt] = x; } if(op == \"pop\"){ hh++; } if(op == \"empty\"){ if(hh <= tt) cout << \"NO\" << endl; else cout << \"YES\" << endl; } if(op == \"query\"){ cout << q[hh] << endl; } } return 0;}\n单调栈\nAcWing 830. 单调栈\n\n#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 100010;int a[N], stk[N], tt = 0;int main(){ int n; cin >> n; for (int i = 0; i < n; i ++ ) scanf(\"%d\", &a[i]); // 单调栈 for (int i = 0; i < n; i ++ ){ while(tt && stk[tt] >= a[i]) tt--; if(tt == 0) cout << -1 << ' '; else cout << stk[tt] << ' '; stk[++tt] = a[i]; } return 0;}\n单调队列\nAcWing 154. 滑动窗口\n\n#include <iostream>using namespace std;const int N = 1000010;int q[N], a[N];int main(){ int n, k; scanf(\"%d%d\", &n, &k); for (int i = 0; i < n; i ++ ) scanf(\"%d\", &a[i]); int hh = 0, tt = -1; for (int i = 0; i < n; i ++ ){ if (hh <= tt && i - k + 1 > q[hh]) hh ++; while (hh <= tt && a[q[tt]] >= a[i]) tt--; q[++tt] = i; if (i - k + 1 >= 0) cout << a[q[hh]] << ' '; } cout << endl; hh = 0, tt = -1; for (int i = 0; i < n; i ++ ){ if (hh <= tt && i - k + 1 > q[hh]) hh ++; while (hh <= tt && a[q[tt]] <= a[i]) tt--; q[++tt] = i; if (i - k + 1 >= 0) cout << a[q[hh]] << ' '; } return 0;}\nkmp\nAcWing 831. KMP字符串\n\n#include <iostream>using namespace std;const int N = 100010;const int M = 1000010;char p[N], s[M];int ne[N];int n, m;int main(){ cin >> n >> p + 1 >> m >> s + 1; // 构造ne for (int i = 2, j = 0; i <= n; i ++ ){ while (j && p[i] != p[j + 1]) j = ne[j]; if (p[i] == p[j + 1]) j ++; ne[i] = j; } // 匹配 for (int i = 1, j = 0; i <= m; i ++){ while (j && s[i] != p[j + 1]) j = ne[j]; if (s[i] == p[j + 1]) j ++; if (j == n){ cout << i - n << ' '; j = ne[j]; } } return 0;}\nTrie\nAcWing 835. Trie字符串统计\n\n#include <iostream>using namespace std;const int N = 100010;int son[N][26], cnt[N], idx;int insert(char s[]){ int p = 0; for (int i = 0; s[i]; i ++){ int u = s[i] - 'a'; if (!son[p][u]) son[p][u] = ++ idx; p = son[p][u]; } cnt[p] ++; return 0;}int query(char s[]){ int p = 0; for (int i = 0; s[i]; i ++){ int u = s[i] - 'a'; if (!son[p][u]) return 0; p = son[p][u]; } return cnt[p];}int main(){ int n; scanf(\"%d\", &n); while (n --){ char op[2], s[N]; scanf(\"%s%s\", op, s); if (op[0] == 'I') insert(s); else cout << query(s) << endl; } return 0;}\n\nAcWing 143. 最大异或对\n\n#include <iostream>using namespace std;const int N = 100010;const int M = 3100010;int a[N];int son[M][2], cnt[M], idx;void insert(int num){ int p = 0; for (int i = 30; i >= 0; i --){ int u = num >> i & 1; if (!son[p][u]) son[p][u] = ++ idx; p = son[p][u]; } cnt[p] ++;}int query(int num){ int p = 0, res = 0; for (int i = 30; i >= 0; i --){ int u = num >> i & 1; if (son[p][!u]) { p = son[p][!u]; res += 1 << i; } else p = son[p][u]; } return res;}int main(){ int n, r = 0; scanf(\"%d\", &n); for (int i = 0; i < n; i ++ ) scanf(\"%d\", &a[i]), insert(a[i]); for (int i = 0; i < n; i ++ ) r = max(r, query(a[i])); printf(\"%d\", r); return 0;}\n并查集\nAcWing 836. 合并集合\n\n#include <iostream>using namespace std;const int N = 100010;int p[N], n, m;int find(int x){ if (p[x] != x) p[x] = find(p[x]); return p[x];}int main(){ scanf(\"%d%d\", &n, &m); for (int i = 1; i <= n; i ++ ) p[i] = i; while (m -- ) { int a, b; char op[2]; scanf(\"%s%d%d\", op, &a, &b); if( op[0] == 'M'){ if (find(a) == find(b)) continue; p[find(a)] = find(b); }else if (op[0] == 'Q'){ if(find(a) == find(b)) cout << \"Yes\" << endl; else cout << \"No\" << endl; } } return 0;}\n\nAcWing 837. 连通块中点的数量\n\n#include <iostream>using namespace std;const int N = 100010;int p[N], cnt[N];int find(int x){ if(p[x] != x) p[x] = find(p[x]); return p[x];}int main(){ int n, m; scanf(\"%d%d\", &n, &m); for (int i = 1; i <= n; i ++ ) p[i] = i, cnt[i] = 1; while (m -- ){ int a, b; string op; cin >> op; if(op == \"C\"){ scanf(\"%d%d\", &a, &b); if(find(a) == find(b)) continue; cnt[find(b)] += cnt[find(a)]; p[find(a)] = find(b); }else if(op == \"Q1\"){ scanf(\"%d%d\", &a, &b); if(find(a) == find(b)) cout << \"Yes\" << endl; else cout << \"No\" << endl; }else if (op == \"Q2\"){ scanf(\"%d\", &a); cout << cnt[find(a)] << endl; } } return 0;}\n\nAcWing 240. 食物链 (不会写)\n\n堆\nAcWing 838. 堆排序\n\n#include <iostream>using namespace std;const int N = 100010;int h[N], cnt;void down(int u){ int t = u; if (u * 2 <= cnt && h[u * 2] < h[t]) t = u * 2; if (u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = u * 2 + 1; if (u != t){ swap(h[u], h[t]); down(t); }}void up(int u){ }int main(){ int n, m; scanf(\"%d%d\", &n, &m); for (int i = 1; i <= n; i ++ ) scanf(\"%d\", &h[i]); cnt = n; for (int i = n / 2; i; i --) down(i); while (m -- ) { printf(\"%d \", h[1]); h[1] = h[cnt --]; down(1); } return 0;}\n\nAcWing 839. 模拟堆\n\n#include <iostream>using namespace std;const int N = 100010;int h[N], cnt, m, hp[N], ph[N];void heap_swap(int a, int b){ swap(ph[hp[a]], ph[hp[b]]); swap(hp[a], hp[b]); swap(h[a], h[b]);}void down(int u){ int t = u; if (2 * u <= cnt && h[2 * u] < h[t]) t = 2 * u; if (2 * u + 1 <= cnt && h[2 * u + 1] < h[t]) t = 2 * u + 1; if (u != t){ heap_swap(t, u); down(t); }}void up(int u){ while (u / 2 && h[u] < h[u / 2]){ heap_swap(u / 2, u); u >>= 1; }}int main(){ int n; scanf(\"%d\", &n); while (n -- ) { string op; int k, x; cin >> op; if (op == \"I\"){ cin >> x; m ++; cnt ++; ph[m] = cnt, hp[cnt] = m; h[cnt] = x; up(cnt); } else if (op == \"PM\"){ cout << h[1] << endl; } else if (op == \"DM\"){ heap_swap(1, cnt); cnt --; down(1); } else if (op == \"D\"){ cin >> k; k = ph[k]; heap_swap(k, cnt); cnt --; up(k); down(k); } else if (op == \"C\"){ cin >> k >> x; k = ph[k]; h[k] = x; up(k); down(k); } } return 0;}\nHash表\nAcWing 840. 模拟散列表\n\n// 拉链法#include <cstring>#include <iostream>using namespace std;const int N = 100003;int h[N], e[N], ne[N], idx;void insert(int x){ int k = (x % N + N) % N; e[idx] = x; ne[idx] = h[k]; h[k] = idx ++;}bool find(int x){ int k = (x % N + N) % N; for (int i = h[k]; i != -1; i = ne[i]){ if (e[i] == x) return true; } return false;}int main(){ int n; scanf(\"%d\", &n); memset(h, -1, sizeof h); while (n -- ) { string op; int x; cin >> op >> x; if (op == \"I\") insert(x); else if (op == \"Q\"){ if(find(x)) cout << \"Yes\" << endl; else cout << \"No\" << endl; } } return 0;}\n\nAcWing 841. 字符串哈希\n\n#include <iostream>using namespace std;typedef unsigned long long ULL;const int N = 200003, P = 131;char s[N];ULL h[N], p[N];int get(int l, int r){ return h[r] - h[l - 1] * p[r - l + 1];}int main(){ int n, m; scanf(\"%d%d\", &n, &m); scanf(\"%s\", s + 1); p[0] = 1; for (int i = 1; i <= n; i ++ ){ h[i] = h[i - 1] * P + s[i]; p[i] = p[i - 1] * P; } while (m -- ) { int l1, r1, l2, r2; scanf(\"%d%d%d%d\", &l1, &r1, &l2, &r2); if (get(l1, r1) == get(l2, r2)) puts(\"Yes\"); else puts(\"No\"); } return 0;}","categories":["算法与数据结构"],"tags":["acwing","算法模板题"]},{"title":"acwing基础算法(4):数学知识","url":"/2022/02/22/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/L4-%E6%95%B0%E5%AD%A6%E7%9F%A5%E8%AF%86/","content":"质数\nAcWing 866. 试除法判定质数\n\n#include <iostream>using namespace std;bool is_prime(int n){ if (n < 2) return false; for (int i = 2; i <= n / i; i ++){ if (n % i == 0) return false; } return true;}int main(){ int n; scanf(\"%d\", &n); while (n -- ) { int x; scanf(\"%d\", &x); if (is_prime(x)) puts(\"Yes\"); else puts(\"No\"); } return 0;}\n\nAcWing 867. 分解质因数\n\n#include <iostream>using namespace std;void divided(int n){ for (int i = 2; i <= n / i; i ++) { if (n % i == 0) { int s = 0; while (n % i == 0) n /= i, s ++; cout << i << ' ' << s << endl; } } if (n > 1) cout << n << ' ' << 1 << endl; cout << endl;}int main(){ int n; cin >>n; while (n -- ){ int x; cin >> x; divided(x); } return 0;}\n\nAcWing 868. 筛质数\n\n朴素筛法#include <iostream>using namespace std;const int N = 1000010;int primes[N], cnt;bool st[N];int count(int n){ for (int i = 2; i <= n; i ++) { if (st[i]) continue; primes[cnt ++] = i; for (int j = i + i; j <= n; j += i) st[j] = true; } return cnt;}int main(){ int n; cin >> n; cout << count(n) << endl; return 0;}\n线性筛法#include <iostream>using namespace std;const int N = 1000010;int primes[N], cnt;bool st[N];// 线性筛法void count(int n){ for (int i = 2; i <= n; i ++) { if (!st[i]) primes[cnt ++] = i; for (int j = 0; primes[j] <= n / i; j ++ ) { st[primes[j] * i] = true; if (i % primes[j] == 0) break; } }}int main(){ int n; cin >> n; count(n); cout << cnt << endl; return 0;}\n约数\nAcWing 869. 试除法求约数\n\n#include <iostream>#include <vector>#include <algorithm>using namespace std;vector<int> get_divisors(int n){ vector<int> res; for (int i = 1; i <= n / i; i ++ ) { if (n % i == 0) { res.push_back(i); if ( i != n / i) res.push_back(n / i); } } sort(res.begin(), res.end()); return res;}int main(){ int n; cin >> n; while (n -- ) { int x; cin >> x; auto res = get_divisors(x); for (auto c : res) cout << c << ' '; puts(\"\"); } return 0;}\n\nAcWing 870. 约数个数\n\n#include <iostream>#include <unordered_map>using namespace std;typedef long long LL;const int N = 1e9 + 7;int main(){ int n; cin >> n; unordered_map<int, int> primes; while (n -- ) { int x; cin >>x; for (int i = 2; i <= x / i; i ++) { while (x % i == 0) { x /= i; primes[i] ++; } } if (x > 1) primes[x] ++; } LL res = 1; for (auto c : primes) { res = res * (c.second + 1) % N; } cout << res << endl;}\n\nAcWing 871. 约数之和\n\n#include <iostream>#include <algorithm>#include <unordered_map>using namespace std;typedef long long LL;const int mod = 1e9 + 7;int main(){ int n; cin >> n; unordered_map<int, int> primes; while (n -- ) { int x; cin >> x; for (int i = 2; i <= x / i; i ++) { while (x % i == 0) x /= i, primes[i] ++; } if (x > 1) primes[x] ++; } LL res = 1; for (auto p : primes) { LL a = p.first, b = p.second; LL t = 1; while (b --) t = (t * a + 1) % mod; res = res * t % mod; } cout << res << endl; return 0;}\n\nAcWing 872. 最大公约数\n\n#include <iostream>using namespace std;int gcd(int a, int b){ return b? gcd(b, a % b) : a;}int main(){ int n; cin >> n; while (n -- ) { int a, b; cin >> a >> b; cout << gcd(a, b) << endl; } return 0;}\n欧拉函数\nAcWing 873. 欧拉函数\n\nAcWing 874. 筛法求欧拉函数\n\n\n快速幂\nAcWing 875. 快速幂\n\n#include <iostream>using namespace std;typedef long long LL;LL qmi(int a, int k, int p){ LL res = 1 % p; while (k) { if (k & 1) res = res * (LL)a % p; a = a * (LL) a % p; k >>= 1; } return res;}int main(){ int n; scanf(\"%d\", &n); while (n -- ) { int a, k, p; scanf(\"%d%d%d\", &a, &k, &p); printf(\"%d\\n\", qmi(a, k, p)); } return 0;}\n\nAcWing 876. 快速幂求逆元\n\n扩展欧几里得算法\nAcWing 877. 扩展欧几里得算法\nAcWing 878. 线性同余方程\n\n中国剩余定理\nAcWing 204. 表达整数的奇怪方式\n\n高斯消元\nAcWing 883. 高斯消元解线性方程组\n\nAcWing 884. 高斯消元解异或线性方程组\n\n\n组合计数\nAcWing 885. 求组合数 I 3301人打卡\n\nAcWing 886. 求组合数 II 2874人打卡\n\nAcWing 887. 求组合数 III 2505人打卡\n\nAcWing 888. 求组合数 IV 2131人打卡\n\nAcWing 889. 满足条件的01序列\n\n\n容斥原理\nAcWing 890. 能被整除的数\n\n简单博弈论\nAcWing 891. Nim游戏 2857人打卡\n\nAcWing 892. 台阶-Nim游戏 2264人打卡\n\nAcWing 893. 集合-Nim游戏 2214人打卡\n\nAcWing 894. 拆分-Nim游戏\n\n\n","categories":["算法与数据结构"],"tags":["acwing","算法模板题"]},{"title":"acwing基础算法(5):动态规划","url":"/2022/02/22/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/L5-%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/","content":"背包问题\nAcWing 2. 01背包问题\n\n二维数组#include <iostream>#include <algorithm>using namespace std;const int N = 1010;int v[N], w[N];int f[N][N];int main(){ int n, m; scanf(\"%d%d\", &n, &m); for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i]; for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= m; j ++) { f[i][j] = f[i - 1][j]; if (j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]); } cout << f[n][m] << endl; return 0;}\n一维数组优化\nAcWing 3. 完全背包问题\n\nAcWing 4. 多重背包问题\n\nAcWing 5. 多重背包问题 II \n\nAcWing 9. 分组背包问题\n\n\n线性DP\nAcWing 898. 数字三角形\n\nAcWing 895. 最长上升子序列\n\nAcWing 896. 最长上升子序列 II\n\nAcWing 897. 最长公共子序列\n\nAcWing 902. 最短编辑距离\n\nAcWing 899. 编辑距离\n\n\n区间DP\nAcWing 282. 石子合并\n\n计数类DP\nAcWing 900. 整数划分\n\n数位统计DP\nAcWing 338. 计数问题\n\n状态压缩DP\nAcWing 291. 蒙德里安的梦想\n\nAcWing 91. 最短Hamilton路径\n\n\n树形DP\nAcWing 285. 没有上司的舞会\n\n记忆化搜索\nAcWing 901. 滑雪\n\n","categories":["算法与数据结构"],"tags":["acwing","算法模板题","dp"]},{"title":"acwing基础算法(6):贪心","url":"/2022/02/22/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/L6-%E8%B4%AA%E5%BF%83/","content":"区间问题\nAcWing 905. 区间选点\n\nAcWing 908. 最大不相交区间数量\n\nAcWing 906. 区间分组\n\nAcWing 907. 区间覆盖\n\n\nHuffman树\nAcWing 148. 合并果子\n\n排序不等式\nAcWing 913. 排队打水\n\n绝对值不等式\nAcWing 104. 货仓选址\n\n推公式\nAcWing 125. 耍杂技的牛\n\n","categories":["算法与数据结构"],"tags":["acwing","算法模板题"]},{"title":"基础算法模板(1):基础算法","url":"/2022/02/18/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/%E6%A8%A1%E6%9D%BF1_%E5%9F%BA%E7%A1%80%E7%AE%97%E6%B3%95/","content":"快速排序算法模板 —— 模板题 AcWing 785. 快速排序\nvoid quick_sort(int q[], int l, int r){ if (l >= r) return; int i = l - 1, j = r + 1, x = q[l + r >> 1]; while (i < j) { do i ++ ; while (q[i] < x); do j -- ; while (q[j] > x); if (i < j) swap(q[i], q[j]); } quick_sort(q, l, j), quick_sort(q, j + 1, r);}\n归并排序算法模板 —— 模板题 AcWing 787. 归并排序\nvoid merge_sort(int q[], int l, int r){ if (l >= r) return; int mid = l + r >> 1; merge_sort(q, l, mid); merge_sort(q, mid + 1, r); int k = 0, i = l, j = mid + 1; while (i <= mid && j <= r) if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ]; else tmp[k ++ ] = q[j ++ ]; while (i <= mid) tmp[k ++ ] = q[i ++ ]; while (j <= r) tmp[k ++ ] = q[j ++ ]; for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];}\n整数二分算法模板 —— 模板题 AcWing 789. 数的范围\nbool check(int x) {/* ... */} // 检查x是否满足某种性质// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:int bsearch_1(int l, int r){ while (l < r) { int mid = l + r >> 1; if (check(mid)) r = mid; // check()判断mid是否满足性质 else l = mid + 1; } return l;}// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:int bsearch_2(int l, int r){ while (l < r) { int mid = l + r + 1 >> 1; if (check(mid)) l = mid; else r = mid - 1; } return l;}\n浮点数二分算法模板 —— 模板题 AcWing 790. 数的三次方根\nbool check(double x) {/* ... */} // 检查x是否满足某种性质double bsearch_3(double l, double r){ const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求 while (r - l > eps) { double mid = (l + r) / 2; if (check(mid)) r = mid; else l = mid; } return l;}\n高精度加法 —— 模板题 AcWing 791. 高精度加法\n// C = A + B, A >= 0, B >= 0vector<int> add(vector<int> &A, vector<int> &B){ if (A.size() < B.size()) return add(B, A); vector<int> C; int t = 0; for (int i = 0; i < A.size(); i ++ ) { t += A[i]; if (i < B.size()) t += B[i]; C.push_back(t % 10); t /= 10; } if (t) C.push_back(t); return C;}\n高精度减法 —— 模板题 AcWing 792. 高精度减法\n// C = A - B, 满足A >= B, A >= 0, B >= 0vector<int> sub(vector<int> &A, vector<int> &B){ vector<int> C; for (int i = 0, t = 0; i < A.size(); i ++ ) { t = A[i] - t; if (i < B.size()) t -= B[i]; C.push_back((t + 10) % 10); if (t < 0) t = 1; else t = 0; } while (C.size() > 1 && C.back() == 0) C.pop_back(); return C;}\n高精度乘低精度 —— 模板题 AcWing 793. 高精度乘法\n// C = A * b, A >= 0, b >= 0vector<int> mul(vector<int> &A, int b){ vector<int> C; int t = 0; for (int i = 0; i < A.size() || t; i ++ ) { if (i < A.size()) t += A[i] * b; C.push_back(t % 10); t /= 10; } while (C.size() > 1 && C.back() == 0) C.pop_back(); return C;}\n高精度除以低精度 —— 模板题 AcWing 794. 高精度除法\n// A / b = C ... r, A >= 0, b > 0vector<int> div(vector<int> &A, int b, int &r){ vector<int> C; r = 0; for (int i = A.size() - 1; i >= 0; i -- ) { r = r * 10 + A[i]; C.push_back(r / b); r %= b; } reverse(C.begin(), C.end()); while (C.size() > 1 && C.back() == 0) C.pop_back(); return C;}\n一维前缀和 —— 模板题 AcWing 795. 前缀和\nS[i] = a[1] + a[2] + ... a[i]a[l] + ... + a[r] = S[r] - S[l - 1]\n二维前缀和 —— 模板题 AcWing 796. 子矩阵的和\nS[i, j] = 第i行j列格子左上部分所有元素的和以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]\n一维差分 —— 模板题 AcWing 797. 差分\n给区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c\n二维差分 —— 模板题 AcWing 798. 差分矩阵\n给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c\n位运算 —— 模板题 AcWing 801. 二进制中1的个数\n求n的第k位数字: n >> k & 1返回n的最后一位1:lowbit(n) = n & -n\n双指针算法 —— 模板题 AcWIng 799. 最长连续不重复子序列, AcWing 800. 数组元素的目标和\nfor (int i = 0, j = 0; i < n; i ++ ){ while (j < i && check(i, j)) j ++ ; // 具体问题的逻辑}常见问题分类: (1) 对于一个序列,用两个指针维护一段区间 (2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作\n离散化 —— 模板题 AcWing 802. 区间和\nvector<int> alls; // 存储所有待离散化的值sort(alls.begin(), alls.end()); // 将所有值排序alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 去掉重复元素// 二分求出x对应的离散化的值int find(int x) // 找到第一个大于等于x的位置{ int l = 0, r = alls.size() - 1; while (l < r) { int mid = l + r >> 1; if (alls[mid] >= x) r = mid; else l = mid + 1; } return r + 1; // 映射到1, 2, ...n}\n区间合并 —— 模板题 AcWing 803. 区间合并\n// 将所有存在交集的区间合并void merge(vector<PII> &segs){ vector<PII> res; sort(segs.begin(), segs.end()); int st = -2e9, ed = -2e9; for (auto seg : segs) if (ed < seg.first) { if (st != -2e9) res.push_back({st, ed}); st = seg.first, ed = seg.second; } else ed = max(ed, seg.second); if (st != -2e9) res.push_back({st, ed}); segs = res;}\n","categories":["算法与数据结构"],"tags":["acwing"]},{"title":"基础算法模板(3):搜索与图论","url":"/2022/02/18/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/%E6%A8%A1%E6%9D%BF3_%E6%90%9C%E7%B4%A2%E4%B8%8E%E5%9B%BE%E8%AE%BA/","content":"树与图的存储\n树是一种特殊的图,与图的存储方式相同。\n对于无向图中的边ab,存储两条有向边a->b, b->a。\n因此我们可以只考虑有向图的存储。\n1) 邻接矩阵:g[a][b] 存储边a->b2) 邻接表\n// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点int h[N], e[N], ne[N], idx;// 添加一条边a->bvoid add(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;}// 初始化idx = 0;memset(h, -1, sizeof h);\n树与图的遍历\n时间复杂度 $O(n+m)$, n 表示点数,m 表示边数\n(1)深度优先遍历 —— 模板题 AcWing 846. 树的重心\nint dfs(int u){ st[u] = true; // st[u] 表示点u已经被遍历过 for (int i = h[u]; i != -1; i = ne[i]) { int j = e[i]; if (!st[j]) dfs(j); }}\n(2) 宽度优先遍历 —— 模板题 AcWing 847. 图中点的层次\nqueue<int> q;st[1] = true; // 表示1号点已经被遍历过q.push(1);while (q.size()){ int t = q.front(); q.pop(); for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (!st[j]) { st[j] = true; // 表示点j已经被遍历过 q.push(j); } }}\n拓扑排序 —— 模板题 AcWing 848. 有向图的拓扑序列\n时间复杂度 $O(n+m)$, n 表示点数,m 表示边数\nbool topsort(){ int hh = 0, tt = -1; // d[i] 存储点i的入度 for (int i = 1; i <= n; i ++ ) if (!d[i]) q[ ++ tt] = i; while (hh <= tt) { int t = q[hh ++ ]; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (-- d[j] == 0) q[ ++ tt] = j; } } // 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。 return tt == n - 1;}\n朴素dijkstra算法 —— 模板题 AcWing 849. Dijkstra求最短路 I\n时间复杂是$O(n^2+m)$, n 表示点数,m 表示边数\nint g[N][N]; // 存储每条边int dist[N]; // 存储1号点到每个点的最短距离bool st[N]; // 存储每个点的最短路是否已经确定// 求1号点到n号点的最短路,如果不存在则返回-1int dijkstra(){ memset(dist, 0x3f, sizeof dist); dist[1] = 0; for (int i = 0; i < n - 1; i ++ ) { int t = -1; // 在还未确定最短路的点中,寻找距离最小的点 for (int j = 1; j <= n; j ++ ) if (!st[j] && (t == -1 || dist[t] > dist[j])) t = j; // 用t更新其他点的距离 for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], dist[t] + g[t][j]); st[t] = true; } if (dist[n] == 0x3f3f3f3f) return -1; return dist[n];}\n堆优化版dijkstra —— 模板题 AcWing 850. Dijkstra求最短路 II\n时间复杂度 $O(mlogn)$, n 表示点数,m 表示边数\ntypedef pair<int, int> PII;int n; // 点的数量int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边int dist[N]; // 存储所有点到1号点的距离bool st[N]; // 存储每个点的最短距离是否已确定// 求1号点到n号点的最短距离,如果不存在,则返回-1int dijkstra(){ memset(dist, 0x3f, sizeof dist); dist[1] = 0; priority_queue<PII, vector<PII>, greater<PII>> heap; heap.push({0, 1}); // first存储距离,second存储节点编号 while (heap.size()) { auto t = heap.top(); heap.pop(); int ver = t.second, distance = t.first; if (st[ver]) continue; st[ver] = true; for (int i = h[ver]; i != -1; i = ne[i]) { int j = e[i]; if (dist[j] > distance + w[i]) { dist[j] = distance + w[i]; heap.push({dist[j], j}); } } } if (dist[n] == 0x3f3f3f3f) return -1; return dist[n];}\nBellman-Ford算法 —— 模板题 AcWing 853. 有边数限制的最短路\n时间复杂度 $O(nm)$, n 表示点数,m 表示边数\n注意在模板题中需要对下面的模板稍作修改,加上备份数组,详情见模板题。\nint n, m; // n表示点数,m表示边数int dist[N]; // dist[x]存储1到x的最短路距离struct Edge // 边,a表示出点,b表示入点,w表示边的权重{ int a, b, w;}edges[M];// 求1到n的最短路距离,如果无法从1走到n,则返回-1。int bellman_ford(){ memset(dist, 0x3f, sizeof dist); dist[1] = 0; // 如果第n次迭代仍然会松弛三角不等式,就说明存在一条长度是n+1的最短路径,由抽屉原理,路径中至少存在两个相同的点,说明图中存在负权回路。 for (int i = 0; i < n; i ++ ) { for (int j = 0; j < m; j ++ ) { int a = edges[j].a, b = edges[j].b, w = edges[j].w; if (dist[b] > dist[a] + w) dist[b] = dist[a] + w; } } if (dist[n] > 0x3f3f3f3f / 2) return -1; return dist[n];}\nspfa 算法(队列优化的Bellman-Ford算法) —— 模板题 AcWing 851. spfa求最短路\n时间复杂度 平均情况下 $O(m)$,最坏情况下 $O(nm)$, n 表示点数,m 表示边数\nint n; // 总点数int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边int dist[N]; // 存储每个点到1号点的最短距离bool st[N]; // 存储每个点是否在队列中// 求1号点到n号点的最短路距离,如果从1号点无法走到n号点则返回-1int spfa(){ memset(dist, 0x3f, sizeof dist); dist[1] = 0; queue<int> q; q.push(1); st[1] = true; while (q.size()) { auto t = q.front(); q.pop(); st[t] = false; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (dist[j] > dist[t] + w[i]) { dist[j] = dist[t] + w[i]; if (!st[j]) // 如果队列中已存在j,则不需要将j重复插入 { q.push(j); st[j] = true; } } } } if (dist[n] == 0x3f3f3f3f) return -1; return dist[n];}\nspfa判断图中是否存在负环 —— 模板题 AcWing 852. spfa判断负环\n时间复杂度是 $O(nm)$, n 表示点数,m 表示边数\nint n; // 总点数int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边int dist[N], cnt[N]; // dist[x]存储1号点到x的最短距离,cnt[x]存储1到x的最短路中经过的点数bool st[N]; // 存储每个点是否在队列中// 如果存在负环,则返回true,否则返回false。bool spfa(){ // 不需要初始化dist数组 // 原理:如果某条最短路径上有n个点(除了自己),那么加上自己之后一共有n+1个点,由抽屉原理一定有两个点相同,所以存在环。 queue<int> q; for (int i = 1; i <= n; i ++ ) { q.push(i); st[i] = true; } while (q.size()) { auto t = q.front(); q.pop(); st[t] = false; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (dist[j] > dist[t] + w[i]) { dist[j] = dist[t] + w[i]; cnt[j] = cnt[t] + 1; if (cnt[j] >= n) return true; // 如果从1号点到x的最短路中包含至少n个点(不包括自己),则说明存在环 if (!st[j]) { q.push(j); st[j] = true; } } } } return false;}\nfloyd算法 —— 模板题 AcWing 854. Floyd求最短路\n时间复杂度是 $O(n^3)$, n 表示点数\n初始化: for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= n; j ++ ) if (i == j) d[i][j] = 0; else d[i][j] = INF;// 算法结束后,d[a][b]表示a到b的最短距离void floyd(){ for (int k = 1; k <= n; k ++ ) for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= n; j ++ ) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);}\n朴素版prim算法 —— 模板题 AcWing 858. Prim算法求最小生成树\n时间复杂度是 $O(n^2+m)$, n 表示点数,m 表示边数\nint n; // n表示点数int g[N][N]; // 邻接矩阵,存储所有边int dist[N]; // 存储其他点到当前最小生成树的距离bool st[N]; // 存储每个点是否已经在生成树中// 如果图不连通,则返回INF(值是0x3f3f3f3f), 否则返回最小生成树的树边权重之和int prim(){ memset(dist, 0x3f, sizeof dist); int res = 0; for (int i = 0; i < n; i ++ ) { int t = -1; for (int j = 1; j <= n; j ++ ) if (!st[j] && (t == -1 || dist[t] > dist[j])) t = j; if (i && dist[t] == INF) return INF; if (i) res += dist[t]; st[t] = true; for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]); } return res;}\nKruskal算法 —— 模板题 AcWing 859. Kruskal算法求最小生成树\n时间复杂度是 $O(mlogm)$, n 表示点数,m 表示边数int n, m; // n是点数,m是边数int p[N]; // 并查集的父节点数组struct Edge // 存储边{ int a, b, w; bool operator< (const Edge &W)const { return w < W.w; }}edges[M];int find(int x) // 并查集核心操作{ if (p[x] != x) p[x] = find(p[x]); return p[x];}int kruskal(){ sort(edges, edges + m); for (int i = 1; i <= n; i ++ ) p[i] = i; // 初始化并查集 int res = 0, cnt = 0; for (int i = 0; i < m; i ++ ) { int a = edges[i].a, b = edges[i].b, w = edges[i].w; a = find(a), b = find(b); if (a != b) // 如果两个连通块不连通,则将这两个连通块合并 { p[a] = b; res += w; cnt ++ ; } } if (cnt < n - 1) return INF; return res; }\n染色法判别二分图 —— 模板题 AcWing 860. 染色法判定二分图时间复杂度是 $O(n+m)$, n 表示点数,m 表示边数\nint n; // n表示点数int h[N], e[M], ne[M], idx; // 邻接表存储图int color[N]; // 表示每个点的颜色,-1表示未染色,0表示白色,1表示黑色// 参数:u表示当前节点,c表示当前点的颜色bool dfs(int u, int c){ color[u] = c; for (int i = h[u]; i != -1; i = ne[i]) { int j = e[i]; if (color[j] == -1) { if (!dfs(j, !c)) return false; } else if (color[j] == c) return false; } return true;}bool check(){ memset(color, -1, sizeof color); bool flag = true; for (int i = 1; i <= n; i ++ ) if (color[i] == -1) if (!dfs(i, 0)) { flag = false; break; } return flag;}\n匈牙利算法 —— 模板题 AcWing 861. 二分图的最大匹配\n时间复杂度是 O(nm), n 表示点数,m 表示边数int n1, n2; // n1表示第一个集合中的点数,n2表示第二个集合中的点数int h[N], e[M], ne[M], idx; // 邻接表存储所有边,匈牙利算法中只会用到从第一个集合指向第二个集合的边,所以这里只用存一个方向的边int match[N]; // 存储第二个集合中的每个点当前匹配的第一个集合中的点是哪个bool st[N]; // 表示第二个集合中的每个点是否已经被遍历过bool find(int x){ for (int i = h[x]; i != -1; i = ne[i]) { int j = e[i]; if (!st[j]) { st[j] = true; if (match[j] == 0 || find(match[j])) { match[j] = x; return true; } } } return false;}// 求最大匹配数,依次枚举第一个集合中的每个点能否匹配第二个集合中的点int res = 0;for (int i = 1; i <= n1; i ++ ){ memset(st, false, sizeof st); if (find(i)) res ++ ;}\n","categories":["算法与数据结构"],"tags":["acwing"]},{"title":"基础算法模板(2):数据结构","url":"/2022/02/18/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/%E6%A8%A1%E6%9D%BF2_%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/","content":"数据结构单链表 —— 模板题 AcWing 826. 单链表\n// head存储链表头,e[]存储节点的值,ne[]存储节点的next指针,idx表示当前用到了哪个节点int head, e[N], ne[N], idx;// 初始化void init(){ head = -1; idx = 0;}// 在链表头插入一个数avoid insert(int a){ e[idx] = a, ne[idx] = head, head = idx ++ ;}// 将头结点删除,需要保证头结点存在void remove(){ head = ne[head];}\n双链表 —— 模板题 AcWing 827. 双链表\n// e[]表示节点的值,l[]表示节点的左指针,r[]表示节点的右指针,idx表示当前用到了哪个节点int e[N], l[N], r[N], idx;// 初始化void init(){ //0是左端点,1是右端点 r[0] = 1, l[1] = 0; idx = 2;}// 在节点a的右边插入一个数xvoid insert(int a, int x){ e[idx] = x; l[idx] = a, r[idx] = r[a]; l[r[a]] = idx, r[a] = idx ++ ;}// 删除节点avoid remove(int a){ l[r[a]] = l[a]; r[l[a]] = r[a];}\n栈 —— 模板题 AcWing 828. 模拟栈\n// tt表示栈顶int stk[N], tt = 0;// 向栈顶插入一个数stk[ ++ tt] = x;// 从栈顶弹出一个数tt -- ;// 栈顶的值stk[tt];// 判断栈是否为空if (tt > 0){}\n队列 —— 模板题 AcWing 829. 模拟队列\n\n普通队列\n\n// hh 表示队头,tt表示队尾int q[N], hh = 0, tt = -1;// 向队尾插入一个数q[ ++ tt] = x;// 从队头弹出一个数hh ++ ;// 队头的值q[hh];// 判断队列是否为空if (hh <= tt){}\n\n循环队列\n\n// hh 表示队头,tt表示队尾的后一个位置int q[N], hh = 0, tt = 0;// 向队尾插入一个数q[tt ++ ] = x;if (tt == N) tt = 0;// 从队头弹出一个数hh ++ ;if (hh == N) hh = 0;// 队头的值q[hh];// 判断队列是否为空if (hh != tt){}\n单调栈 —— 模板题 AcWing 830. 单调栈\n常见模型:找出每个数左边离它最近的比它大/小的数int tt = 0;for (int i = 1; i <= n; i ++ ){ while (tt && check(stk[tt], i)) tt -- ; stk[ ++ tt] = i;}\n单调队列 —— 模板题 AcWing 154. 滑动窗口\n常见模型:找出滑动窗口中的最大值/最小值int hh = 0, tt = -1;for (int i = 0; i < n; i ++ ){ while (hh <= tt && check_out(q[hh])) hh ++ ; // 判断队头是否滑出窗口 while (hh <= tt && check(q[tt], i)) tt -- ; q[ ++ tt] = i;}\nKMP —— 模板题 AcWing 831. KMP字符串\n// s[]是长文本,p[]是模式串,n是s的长度,m是p的长度求模式串的Next数组:for (int i = 2, j = 0; i <= m; i ++ ){ while (j && p[i] != p[j + 1]) j = ne[j]; if (p[i] == p[j + 1]) j ++ ; ne[i] = j;}// 匹配for (int i = 1, j = 0; i <= n; i ++ ){ while (j && s[i] != p[j + 1]) j = ne[j]; if (s[i] == p[j + 1]) j ++ ; if (j == m) { j = ne[j]; // 匹配成功后的逻辑 }}\nTrie树 —— 模板题 AcWing 835. Trie字符串统计\nint son[N][26], cnt[N], idx;// 0号点既是根节点,又是空节点// son[][]存储树中每个节点的子节点// cnt[]存储以每个节点结尾的单词数量// 插入一个字符串void insert(char *str){ int p = 0; for (int i = 0; str[i]; i ++ ) { int u = str[i] - 'a'; if (!son[p][u]) son[p][u] = ++ idx; p = son[p][u]; } cnt[p] ++ ;}// 查询字符串出现的次数int query(char *str){ int p = 0; for (int i = 0; str[i]; i ++ ) { int u = str[i] - 'a'; if (!son[p][u]) return 0; p = son[p][u]; } return cnt[p];}\n并查集 —— 模板题 AcWing 836. 合并集合, AcWing 837. 连通块中点的数量\n(1)朴素并查集: int p[N]; //存储每个点的祖宗节点 // 返回x的祖宗节点 int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } // 初始化,假定节点编号是1~n for (int i = 1; i <= n; i ++ ) p[i] = i; // 合并a和b所在的两个集合: p[find(a)] = find(b);(2)维护size的并查集: int p[N], size[N]; //p[]存储每个点的祖宗节点, size[]只有祖宗节点的有意义,表示祖宗节点所在集合中的点的数量 // 返回x的祖宗节点 int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } // 初始化,假定节点编号是1~n for (int i = 1; i <= n; i ++ ) { p[i] = i; size[i] = 1; } // 合并a和b所在的两个集合: size[find(b)] += size[find(a)]; p[find(a)] = find(b);(3)维护到祖宗节点距离的并查集: int p[N], d[N]; //p[]存储每个点的祖宗节点, d[x]存储x到p[x]的距离 // 返回x的祖宗节点 int find(int x) { if (p[x] != x) { int u = find(p[x]); d[x] += d[p[x]]; p[x] = u; } return p[x]; } // 初始化,假定节点编号是1~n for (int i = 1; i <= n; i ++ ) { p[i] = i; d[i] = 0; } // 合并a和b所在的两个集合: p[find(a)] = find(b); d[find(a)] = distance; // 根据具体问题,初始化find(a)的偏移量\n堆 —— 模板题 AcWing 838. 堆排序, AcWing 839. 模拟堆\n// h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1// ph[k]存储第k个插入的点在堆中的位置// hp[k]存储堆中下标是k的点是第几个插入的int h[N], ph[N], hp[N], size;// 交换两个点,及其映射关系void heap_swap(int a, int b){ swap(ph[hp[a]],ph[hp[b]]); swap(hp[a], hp[b]); swap(h[a], h[b]);}void down(int u){ int t = u; if (u * 2 <= size && h[u * 2] < h[t]) t = u * 2; if (u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1; if (u != t) { heap_swap(u, t); down(t); }}void up(int u){ while (u / 2 && h[u] < h[u / 2]) { heap_swap(u, u / 2); u >>= 1; }}// O(n)建堆for (int i = n / 2; i; i -- ) down(i);\n一般哈希 —— 模板题 AcWing 840. 模拟散列表\n(1) 拉链法 int h[N], e[N], ne[N], idx; // 向哈希表中插入一个数 void insert(int x) { int k = (x % N + N) % N; e[idx] = x; ne[idx] = h[k]; h[k] = idx ++ ; } // 在哈希表中查询某个数是否存在 bool find(int x) { int k = (x % N + N) % N; for (int i = h[k]; i != -1; i = ne[i]) if (e[i] == x) return true; return false; }(2) 开放寻址法 int h[N]; // 如果x在哈希表中,返回x的下标;如果x不在哈希表中,返回x应该插入的位置 int find(int x) { int t = (x % N + N) % N; while (h[t] != null && h[t] != x) { t ++ ; if (t == N) t = 0; } return t; }\n字符串哈希 —— 模板题 AcWing 841. 字符串哈希\n核心思想:将字符串看成P进制数,P的经验值是131或13331,取这两个值的冲突概率低小技巧:取模的数用2^64,这样直接用unsigned long long存储,溢出的结果就是取模的结果typedef unsigned long long ULL;ULL h[N], p[N]; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64// 初始化p[0] = 1;for (int i = 1; i <= n; i ++ ){ h[i] = h[i - 1] * P + str[i]; p[i] = p[i - 1] * P;}// 计算子串 str[l ~ r] 的哈希值ULL get(int l, int r){ return h[r] - h[l - 1] * p[r - l + 1];}\nC++ STL简介\nvector, 变长数组,倍增的思想 size() 返回元素个数 empty() 返回是否为空 clear() 清空 front()/back() push_back()/pop_back() begin()/end() [] 支持比较运算,按字典序pair<int, int> first, 第一个元素 second, 第二个元素 支持比较运算,以first为第一关键字,以second为第二关键字(字典序)string,字符串 size()/length() 返回字符串长度 empty() clear() substr(起始下标,(子串长度)) 返回子串 c_str() 返回字符串所在字符数组的起始地址queue, 队列 size() empty() push() 向队尾插入一个元素 front() 返回队头元素 back() 返回队尾元素 pop() 弹出队头元素priority_queue, 优先队列,默认是大根堆 size() empty() push() 插入一个元素 top() 返回堆顶元素 pop() 弹出堆顶元素 定义成小根堆的方式:priority_queue<int, vector<int>, greater<int>> q;stack, 栈 size() empty() push() 向栈顶插入一个元素 top() 返回栈顶元素 pop() 弹出栈顶元素deque, 双端队列 size() empty() clear() front()/back() push_back()/pop_back() push_front()/pop_front() begin()/end() []set, map, multiset, multimap, 基于平衡二叉树(红黑树),动态维护有序序列 size() empty() clear() begin()/end() ++, -- 返回前驱和后继,时间复杂度 O(logn) set/multiset insert() 插入一个数 find() 查找一个数 count() 返回某一个数的个数 erase() (1) 输入是一个数x,删除所有x O(k + logn) (2) 输入一个迭代器,删除这个迭代器 lower_bound()/upper_bound() lower_bound(x) 返回大于等于x的最小的数的迭代器 upper_bound(x) 返回大于x的最小的数的迭代器 map/multimap insert() 插入的数是一个pair erase() 输入的参数是pair或者迭代器 find() [] 注意multimap不支持此操作。 时间复杂度是 O(logn) lower_bound()/upper_bound()unordered_set, unordered_map, unordered_multiset, unordered_multimap, 哈希表 和上面类似,增删改查的时间复杂度是 O(1) 不支持 lower_bound()/upper_bound(), 迭代器的++,--bitset, 圧位 bitset<10000> s; ~, &, |, ^ >>, << ==, != [] count() 返回有多少个1 any() 判断是否至少有一个1 none() 判断是否全为0 set() 把所有位置成1 set(k, v) 将第k位变成v reset() 把所有位变成0 flip() 等价于~ flip(k) 把第k位取反\n","categories":["算法与数据结构"],"tags":["acwing"]},{"title":"基础算法模板(4):数学知识","url":"/2022/02/18/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/%E6%A8%A1%E6%9D%BF4_%E6%95%B0%E5%AD%A6%E7%9F%A5%E8%AF%86/","content":"试除法判定质数 —— 模板题 AcWing 866. 试除法判定质数bool is_prime(int x){ if (x < 2) return false; for (int i = 2; i <= x / i; i ++ ) if (x % i == 0) return false; return true;}\n试除法分解质因数 —— 模板题 AcWing 867. 分解质因数void divide(int x){ for (int i = 2; i <= x / i; i ++ ) if (x % i == 0) { int s = 0; while (x % i == 0) x /= i, s ++ ; cout << i << ' ' << s << endl; } if (x > 1) cout << x << ' ' << 1 << endl; cout << endl;}\n朴素筛法求素数 —— 模板题 AcWing 868. 筛质数int primes[N], cnt; // primes[]存储所有素数bool st[N]; // st[x]存储x是否被筛掉void get_primes(int n){ for (int i = 2; i <= n; i ++ ) { if (st[i]) continue; primes[cnt ++ ] = i; for (int j = i + i; j <= n; j += i) st[j] = true; }}\n线性筛法求素数 —— 模板题 AcWing 868. 筛质数int primes[N], cnt; // primes[]存储所有素数bool st[N]; // st[x]存储x是否被筛掉void get_primes(int n){ for (int i = 2; i <= n; i ++ ) { if (!st[i]) primes[cnt ++ ] = i; for (int j = 0; primes[j] <= n / i; j ++ ) { st[primes[j] * i] = true; if (i % primes[j] == 0) break; } }}\n试除法求所有约数 —— 模板题 AcWing 869. 试除法求约数vector<int> get_divisors(int x){ vector<int> res; for (int i = 1; i <= x / i; i ++ ) if (x % i == 0) { res.push_back(i); if (i != x / i) res.push_back(x / i); } sort(res.begin(), res.end()); return res;}约数个数和约数之和 —— 模板题 AcWing 870. 约数个数, AcWing 871. 约数之和如果 N = p1^c1 * p2^c2 * ... *pk^ck约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)欧几里得算法 —— 模板题 AcWing 872. 最大公约数int gcd(int a, int b){ return b ? gcd(b, a % b) : a;}求欧拉函数 —— 模板题 AcWing 873. 欧拉函数int phi(int x){ int res = x; for (int i = 2; i <= x / i; i ++ ) if (x % i == 0) { res = res / i * (i - 1); while (x % i == 0) x /= i; } if (x > 1) res = res / x * (x - 1); return res;}筛法求欧拉函数 —— 模板题 AcWing 874. 筛法求欧拉函数int primes[N], cnt; // primes[]存储所有素数int euler[N]; // 存储每个数的欧拉函数bool st[N]; // st[x]存储x是否被筛掉void get_eulers(int n){ euler[1] = 1; for (int i = 2; i <= n; i ++ ) { if (!st[i]) { primes[cnt ++ ] = i; euler[i] = i - 1; } for (int j = 0; primes[j] <= n / i; j ++ ) { int t = primes[j] * i; st[t] = true; if (i % primes[j] == 0) { euler[t] = euler[i] * primes[j]; break; } euler[t] = euler[i] * (primes[j] - 1); } }}快速幂 —— 模板题 AcWing 875. 快速幂求 m^k mod p,时间复杂度 O(logk)。int qmi(int m, int k, int p){ int res = 1 % p, t = m; while (k) { if (k&1) res = res * t % p; t = t * t % p; k >>= 1; } return res;}扩展欧几里得算法 —— 模板题 AcWing 877. 扩展欧几里得算法// 求x, y,使得ax + by = gcd(a, b)int exgcd(int a, int b, int &x, int &y){ if (!b) { x = 1; y = 0; return a; } int d = exgcd(b, a % b, y, x); y -= (a/b) * x; return d;}高斯消元 —— 模板题 AcWing 883. 高斯消元解线性方程组// a[N][N]是增广矩阵int gauss(){ int c, r; for (c = 0, r = 0; c < n; c ++ ) { int t = r; for (int i = r; i < n; i ++ ) // 找到绝对值最大的行 if (fabs(a[i][c]) > fabs(a[t][c])) t = i; if (fabs(a[t][c]) < eps) continue; for (int i = c; i <= n; i ++ ) swap(a[t][i], a[r][i]); // 将绝对值最大的行换到最顶端 for (int i = n; i >= c; i -- ) a[r][i] /= a[r][c]; // 将当前行的首位变成1 for (int i = r + 1; i < n; i ++ ) // 用当前行将下面所有的列消成0 if (fabs(a[i][c]) > eps) for (int j = n; j >= c; j -- ) a[i][j] -= a[r][j] * a[i][c]; r ++ ; } if (r < n) { for (int i = r; i < n; i ++ ) if (fabs(a[i][n]) > eps) return 2; // 无解 return 1; // 有无穷多组解 } for (int i = n - 1; i >= 0; i -- ) for (int j = i + 1; j < n; j ++ ) a[i][n] -= a[i][j] * a[j][n]; return 0; // 有唯一解}递归法求组合数 —— 模板题 AcWing 885. 求组合数 // c[a][b] 表示从a个苹果中选b个的方案数for (int i = 0; i < N; i ++ ) for (int j = 0; j <= i; j ++ ) if (!j) c[i][j] = 1; else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;\n通过预处理逆元的方式求组合数 —— 模板题 AcWing 886. 求组合数 II首先预处理出所有阶乘取模的余数fact[N],以及所有阶乘取模的逆元infact[N]如果取模的数是质数,可以用费马小定理求逆元int qmi(int a, int k, int p) // 快速幂模板{ int res = 1; while (k) { if (k & 1) res = (LL)res * a % p; a = (LL)a * a % p; k >>= 1; } return res;}// 预处理阶乘的余数和阶乘逆元的余数fact[0] = infact[0] = 1;for (int i = 1; i < N; i ++ ){ fact[i] = (LL)fact[i - 1] * i % mod; infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;}Lucas定理 —— 模板题 AcWing 887. 求组合数 III若p是质数,则对于任意整数 1 <= m <= n,有: C(n, m) = C(n % p, m % p) * C(n / p, m / p) (mod p)int qmi(int a, int k, int p) // 快速幂模板{ int res = 1 % p; while (k) { if (k & 1) res = (LL)res * a % p; a = (LL)a * a % p; k >>= 1; } return res;}int C(int a, int b, int p) // 通过定理求组合数C(a, b){ if (a < b) return 0; LL x = 1, y = 1; // x是分子,y是分母 for (int i = a, j = 1; j <= b; i --, j ++ ) { x = (LL)x * i % p; y = (LL) y * j % p; } return x * (LL)qmi(y, p - 2, p) % p;}int lucas(LL a, LL b, int p){ if (a < p && b < p) return C(a, b, p); return (LL)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;}分解质因数法求组合数 —— 模板题 AcWing 888. 求组合数 IV当我们需要求出组合数的真实值,而非对某个数的余数时,分解质因数的方式比较好用: 1. 筛法求出范围内的所有质数 2. 通过 C(a, b) = a! / b! / (a - b)! 这个公式求出每个质因子的次数。 n! 中p的次数是 n / p + n / p^2 + n / p^3 + ... 3. 用高精度乘法将所有质因子相乘int primes[N], cnt; // 存储所有质数int sum[N]; // 存储每个质数的次数bool st[N]; // 存储每个数是否已被筛掉void get_primes(int n) // 线性筛法求素数{ for (int i = 2; i <= n; i ++ ) { if (!st[i]) primes[cnt ++ ] = i; for (int j = 0; primes[j] <= n / i; j ++ ) { st[primes[j] * i] = true; if (i % primes[j] == 0) break; } }}int get(int n, int p) // 求n!中的次数{ int res = 0; while (n) { res += n / p; n /= p; } return res;}vector<int> mul(vector<int> a, int b) // 高精度乘低精度模板{ vector<int> c; int t = 0; for (int i = 0; i < a.size(); i ++ ) { t += a[i] * b; c.push_back(t % 10); t /= 10; } while (t) { c.push_back(t % 10); t /= 10; } return c;}get_primes(a); // 预处理范围内的所有质数for (int i = 0; i < cnt; i ++ ) // 求每个质因数的次数{ int p = primes[i]; sum[i] = get(a, p) - get(b, p) - get(a - b, p);}vector<int> res;res.push_back(1);for (int i = 0; i < cnt; i ++ ) // 用高精度乘法将所有质因子相乘 for (int j = 0; j < sum[i]; j ++ ) res = mul(res, primes[i]);卡特兰数 —— 模板题 AcWing 889. 满足条件的01序列给定n个0和n个1,它们按照某种顺序排成长度为2n的序列,满足任意前缀中0的个数都不少于1的个数的序列的数量为: Cat(n) = C(2n, n) / (n + 1)NIM游戏 —— 模板题 AcWing 891. Nim游戏给定N堆物品,第i堆物品有Ai个。两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。取走最后一件物品者获胜。两人都采取最优策略,问先手是否必胜。我们把这种游戏称为NIM博弈。把游戏过程中面临的状态称为局面。整局游戏第一个行动的称为先手,第二个行动的称为后手。若在某一局面下无论采取何种行动,都会输掉游戏,则称该局面必败。所谓采取最优策略是指,若在某一局面下存在某种行动,使得行动后对面面临必败局面,则优先采取该行动。同时,这样的局面被称为必胜。我们讨论的博弈问题一般都只考虑理想情况,即两人均无失误,都采取最优策略行动时游戏的结果。NIM博弈不存在平局,只有先手必胜和先手必败两种情况。定理: NIM博弈先手必胜,当且仅当 A1 ^ A2 ^ … ^ An != 0公平组合游戏ICG若一个游戏满足:由两名玩家交替行动;在游戏进程的任意时刻,可以执行的合法行动与轮到哪名玩家无关;不能行动的玩家判负;则称该游戏为一个公平组合游戏。NIM博弈属于公平组合游戏,但城建的棋类游戏,比如围棋,就不是公平组合游戏。因为围棋交战双方分别只能落黑子和白子,胜负判定也比较复杂,不满足条件2和条件3。有向图游戏给定一个有向无环图,图中有一个唯一的起点,在起点上放有一枚棋子。两名玩家交替地把这枚棋子沿有向边进行移动,每次可以移动一步,无法移动者判负。该游戏被称为有向图游戏。任何一个公平组合游戏都可以转化为有向图游戏。具体方法是,把每个局面看成图中的一个节点,并且从每个局面向沿着合法行动能够到达的下一个局面连有向边。Mex运算设S表示一个非负整数集合。定义mex(S)为求出不属于集合S的最小非负整数的运算,即:mex(S) = min{x}, x属于自然数,且x不属于SSG函数在有向图游戏中,对于每个节点x,设从x出发共有k条有向边,分别到达节点y1, y2, …, yk,定义SG(x)为x的后继节点y1, y2, …, yk 的SG函数值构成的集合再执行mex(S)运算的结果,即:SG(x) = mex({SG(y1), SG(y2), …, SG(yk)})特别地,整个有向图游戏G的SG函数值被定义为有向图游戏起点s的SG函数值,即SG(G) = SG(s)。有向图游戏的和 —— 模板题 AcWing 893. 集合-Nim游戏设G1, G2, …, Gm 是m个有向图游戏。定义有向图游戏G,它的行动规则是任选某个有向图游戏Gi,并在Gi上行动一步。G被称为有向图游戏G1, G2, …, Gm的和。有向图游戏的和的SG函数值等于它包含的各个子游戏SG函数值的异或和,即:SG(G) = SG(G1) ^ SG(G2) ^ … ^ SG(Gm)定理有向图游戏的某个局面必胜,当且仅当该局面对应节点的SG函数值大于0。有向图游戏的某个局面必败,当且仅当该局面对应节点的SG函数值等于0。\n","categories":["算法与数据结构"],"tags":["acwing"]},{"title":"2014级软件学院算法分析与设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2014%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90%E4%B8%8E%E8%AE%BE%E8%AE%A1/C1-2014%E7%BA%A7%E7%AE%97%E6%B3%95%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"链接:2014级算法第一次上机\n\n未完成 B, C, D , F\nA 零崎的人间冒险Ⅰ\n汉诺塔问题, 直接递归+模拟\n\nn = 1时:\n\nA —> C\n\nn = 2时:\n\nA —> B\nA —> C\nB —> C\n\nn = 3时:\n\nA —> C\nA —> B\nC —> B\nA —> C\nB —> A\nB —> C\nA —> C\n\n可以发现,要实现n个盘子的移动:\n\n首先要把前n-1个盘子从A杆移动到B杆上\n在把第n个盘子从A杆移动到C杆上\n最后把前n-1个盘子从B杆移动到C杆上\n\n/* Author: 武迪 Result: AC\tSubmission_id: 4107444 Created at: Wed Feb 23 2022 15:06:14 GMT+0800 (China Standard Time) Problem_id: 9\tTime: 96\tMemory: 3348*/#include <iostream>using namespace std;void hanoi(int n, char A, char B, char C){ if (n == 1) cout << A << " to " << C << endl; else { hanoi(n - 1, A, C, B); cout << A << " to " << C << endl; hanoi(n - 1, B, A, C); }}int main(){ int n; while(cin >> n) { hanoi(n, 'A', 'B', 'C'); puts(""); } return 0;}\nB 零崎的人间冒险ⅡC Let’s play a gameD 零崎的人间冒险ⅢE Inverse number:Reborn\n思路:直接归并排序\n\n/* Author: 武迪 Result: AC\tSubmission_id: 4095274 Created at: Fri Jan 07 2022 23:40:56 GMT+0800 (China Standard Time) Problem_id: 14\tTime: 124\tMemory: 4200*/#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 100010;int q[N], tmp[N], n;unsigned long res = 0;void merge_sort(int q[], int l, int r){ if (l >= r) return; int mid = l + r >> 1; merge_sort(q, l, mid); merge_sort(q, mid + 1, r); int k = 0, i = l, j = mid + 1; while (i <= mid && j <= r){ if(q[i] <= q[j]) tmp[k++] = q[i++]; else{ tmp[k++] = q[j++]; res += mid - i + 1; } } while (i <= mid) tmp[k++] = q[i++]; while (j <= r) tmp[k++] = q[j++]; for(i=l, j=0;i<=r;i++,j++) q[i] = tmp[j];}int main(){ while (scanf("%d", &n) != EOF) { for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]); res = 0; merge_sort(q, 0, n - 1); cout << res << endl; } return 0; }\nF 零崎的人间冒险Ⅳ","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2014级软件学院算法分析与设计 - 第二次上机","url":"/2022/02/20/algorithm/oj4th/2014%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90%E4%B8%8E%E8%AE%BE%E8%AE%A1/C2-2014%E7%BA%A7%E7%AE%97%E6%B3%95%E7%AC%AC%E4%BA%8C%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2014级软件学院算法分析与设计 - 第三次上机","url":"/2022/02/20/algorithm/oj4th/2014%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90%E4%B8%8E%E8%AE%BE%E8%AE%A1/C3-2014%E7%BA%A7%E7%AE%97%E6%B3%95%E7%AC%AC%E4%B8%89%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2014级软件学院算法分析与设计 - 第四次上机","url":"/2022/02/20/algorithm/oj4th/2014%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90%E4%B8%8E%E8%AE%BE%E8%AE%A1/C4-2014%E7%BA%A7%E7%AE%97%E6%B3%95%E7%AC%AC%E5%9B%9B%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2014级软件学院算法分析与设计 - 第五次上机","url":"/2022/02/20/algorithm/oj4th/2014%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90%E4%B8%8E%E8%AE%BE%E8%AE%A1/C5-2014%E7%BA%A7%E7%AE%97%E6%B3%95%E7%AC%AC%E4%BA%94%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2014级软件学院算法分析与设计 - 第六次上机","url":"/2022/02/20/algorithm/oj4th/2014%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90%E4%B8%8E%E8%AE%BE%E8%AE%A1/C6-2014%E7%BA%A7%E7%AE%97%E6%B3%95%E7%AC%AC%E5%85%AD%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2014级软件学院算法分析与设计-算法练习赛","url":"/2022/02/20/algorithm/oj4th/2014%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90%E4%B8%8E%E8%AE%BE%E8%AE%A1/%E7%AE%97%E6%B3%95%E7%BB%83%E4%B9%A0%E8%B5%9B/","content":"/* Author: 武迪 Result: AC\tSubmission_id: 4095286 Created at: Sat Jan 08 2022 01:02:04 GMT+0800 (China Standard Time) Problem_id: 39\tTime: 10\tMemory: 3424*/#include <iostream>using namespace std;const int N = 250010;int a[N];int main(){ int n, m; while (cin >> n >> m) { for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]); while (m -- ) { int x; cin >> x; int l = 0, r = n - 1; while (l < r) { int mid = l + r >> 1; if(a[mid] >= x) r = mid; else l = mid + 1; } if (a[l] != x) cout << "error" << endl; else cout << l + 1 << endl; } } return 0;}\n","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/C1-2015%E7%BA%A7C++%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"/* Author: 武迪 Result: AC\tSubmission_id: 4095276 Created at: Fri Jan 07 2022 23:47:56 GMT+0800 (China Standard Time) Problem_id: 18\tTime: 20\tMemory: 3528*/#include <iostream>using namespace std;int main(){ double a, b, c; cin >> a >> b >> c; printf("%.2f", (a + b + c) / 3); return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095277 Created at: Fri Jan 07 2022 23:51:47 GMT+0800 (China Standard Time) Problem_id: 19\tTime: 5\tMemory: 3432*/#include <iostream>using namespace std;int main(){ int n; cin >> n; int res = n % 3? n / 3 + 1 :n / 3; cout << res << endl; return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095279 Created at: Sat Jan 08 2022 00:05:38 GMT+0800 (China Standard Time) Problem_id: 20\tTime: 28\tMemory: 3308*/#include <iostream>#include <vector>using namespace std;int main(){ long long a, b; cin >> a >> b; cout << a + b << endl; return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095280 Created at: Sat Jan 08 2022 00:11:36 GMT+0800 (China Standard Time) Problem_id: 21\tTime: 1\tMemory: 3444*/#include <iostream>using namespace std;int main(){ double n; while (cin >> n){ if (n >= 90 && n <= 100) cout << 'A' << endl; else if (n >= 80 && n < 90) cout << "B" << endl; else if (n >= 70 && n < 80) cout << "C" << endl; else if (n >= 60 && n < 70) cout << "D" << endl; else if (n >= 0 && n < 60) cout << "E" << endl; else cout << "wrong" << endl; } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095282 Created at: Sat Jan 08 2022 00:15:37 GMT+0800 (China Standard Time) Problem_id: 22\tTime: 4\tMemory: 3368*/#include <iostream>using namespace std;int main(){ cout << "//\\\\\\\\^'\\\\n#s)\\\\tF*//\\\\r" << endl; cout << endl; cout << "http://i.youku.com/microhhh" << endl; return 0;}\n","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/C2-2015%E7%BA%A7C++%E7%AC%AC%E4%BA%8C%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"/* Author: 武迪 Result: AC\tSubmission_id: 4095316 Created at: Sat Jan 08 2022 13:18:56 GMT+0800 (China Standard Time) Problem_id: 32\tTime: 436\tMemory: 3432*/#include <iostream>using namespace std;int main(){ int n, m; while (scanf("%d%d", &n, &m) !=EOF) { if (n == m) cout << n << ' ' << 0 << endl; else if (n > m) cout << m << ' ' << (n - m) / 2 << endl; else cout << n << ' ' << (m - n) / 2 << endl; } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095325 Created at: Sat Jan 08 2022 14:03:49 GMT+0800 (China Standard Time) Problem_id: 34\tTime: 4\tMemory: 3404*/#include <iostream>using namespace std;int main(){ int a, b, c; while (scanf("%d%d%d", &a, &b, &c) != EOF) { if (a + b > c && a + c > b && b + c > a){ if (a * a + b * b == c * c || a * a + c * c == b * b || c * c + b * b == a * a) cout << "good" << endl; else if (a == b || a == c || b == c) cout << "perfect" << endl; else cout << "just a triangle" << endl; }else cout << "wrong" << endl; } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095410 Created at: Sat Jan 08 2022 21:30:24 GMT+0800 (China Standard Time) Problem_id: 35\tTime: 42\tMemory: 3456*/#include <iostream>using namespace std;int main(){ int n; while (scanf("%d", &n) != EOF) { n += 2; while (n % 3 == 0) n /= 3; while (n % 5 == 0) n /= 5; if (n == 1) printf("Yes\\n"); else printf("No\\n"); } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095329 Created at: Sat Jan 08 2022 14:12:25 GMT+0800 (China Standard Time) Problem_id: 36\tTime: 801\tMemory: 3600*/#include <iostream>using namespace std;int main(){ int n, m, k; while (scanf("%d%d", &n, &m) != EOF) { k = n / m; printf("%d %d\\n", k, k * m); } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095290 Created at: Sat Jan 08 2022 01:16:06 GMT+0800 (China Standard Time) Problem_id: 37\tTime: 4\tMemory: 3472*/#include <iostream>using namespace std;const double eps = 0.0000001;int main(){ double n, m; while (cin >> n >> m) { if (n - m >= eps) cout << "woshibukezhanshengde"<< endl; if (m - n >= eps) cout << "wohenbaoqian" << endl; if (n - m < eps && n - m > -eps) cout << "nakezhenchun" << endl; } return 0;}\n","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/C3-2015%E7%BA%A7C++%E7%AC%AC%E4%B8%89%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/C4-2015%E7%BA%A7C++%E7%AC%AC%E5%9B%9B%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/C5-2015%E7%BA%A7C++%E7%AC%AC%E4%BA%94%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/C6-2015%E7%BA%A7C++%E7%AC%AC%E5%85%AD%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/C7-2015%E7%BA%A7C++%E7%AC%AC%E4%B8%83%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/C8-2015%E7%BA%A7C++%E7%AC%AC%E5%85%AB%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/C9-2015%E7%BA%A7C++%E7%AC%AC%E4%B9%9D%E6%AC%A1%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E1-%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%AF%94%E8%B5%9B/","content":"/* Author: 武迪 Result: AC\tSubmission_id: 4095073 Created at: Thu Jan 06 2022 15:27:50 GMT+0800 (China Standard Time) Problem_id: 2\tTime: 2\tMemory: 1540*/#include <stdio.h>int main(){ int n, m; scanf("%d%d", &n, &m); printf("%d", n%m); return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095074 Created at: Thu Jan 06 2022 15:30:17 GMT+0800 (China Standard Time) Problem_id: 3\tTime: 2\tMemory: 1632*/#include<stdio.h>int main(){ int n, m, k; while(scanf("%d%d%d", &n, &m, &k)!=EOF){ int sum = n; while (k){ int p = n + m * k; sum += p; k --; } printf("%d\\n", sum); } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095076 Created at: Thu Jan 06 2022 15:35:21 GMT+0800 (China Standard Time) Problem_id: 4\tTime: 2\tMemory: 1348*/#include<stdio.h>int main(){ char s[] = "\\"\\\\a\\\\t\\\\0\\\\y\\\\a\\\\n\\\\g\\""; printf("%s", s); return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095262 Created at: Fri Jan 07 2022 23:02:00 GMT+0800 (China Standard Time) Problem_id: 5\tTime: 222\tMemory: 20184*/#include <iostream>#include <string>using namespace std;int fun(int n){ int sum = 0; while (n > 0){ sum += n % 10; n /= 10; } if (sum >= 10) return fun(sum); else return sum;}int main(){ string s; cin >> s; int res = 0; for (int i = 0; i < s.size(); i ++ ) res += (s[i] - '0'); cout << fun(res) << endl; return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095077 Created at: Thu Jan 06 2022 15:57:08 GMT+0800 (China Standard Time) Problem_id: 6\tTime: 3\tMemory: 3320*/#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 10;int main(){ string s; while (cin >> s){ while (s.size() > 1 && s.back() == '0') s.pop_back(); reverse(s.begin(), s.end()); cout << s << endl; } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095082 Created at: Thu Jan 06 2022 16:21:58 GMT+0800 (China Standard Time) Problem_id: 7\tTime: 2\tMemory: 3420*/#include <iostream>#include <vector>using namespace std;string print_shape(int n, int m){ string res; int n1 = n, n2 = n; while (n1 -- ) res += " "; while (m -- ) res += "#"; while (n2 -- ) res += " "; return res; }int main(){ int n; while (cin >> n){ int length = 2 * n - 1; while (n) { int sharps = 2 * n - 1; int blocks = (length - sharps) / 2; string s = print_shape(blocks, sharps); cout << s << endl; n -- ; } } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095257 Created at: Fri Jan 07 2022 22:45:00 GMT+0800 (China Standard Time) Problem_id: 8\tTime: 5\tMemory: 3284*/#include <iostream>#include <cstring>#include <algorithm>using namespace std;int T;int main(){ cin >> T; while (T --) { int a, b, c, d, e, f, g, h; cin >> a >> b >> c >> d >> e >> f >> g >> h; int res = (a * c) / b + (d * g * h) / (e * f); cout << res << endl; } return 0;}\n","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E2-2015%E7%BA%A7C++%E7%AC%AC%E4%BA%8C%E6%AC%A1%E7%BB%83%E4%B9%A0/","content":"/* Author: 武迪 Result: AC\tSubmission_id: 4095284 Created at: Sat Jan 08 2022 00:29:45 GMT+0800 (China Standard Time) Problem_id: 23\tTime: 2\tMemory: 3344*/#include <iostream>using namespace std;int a, b, c, t;bool fun(int a){ if (a <= b){ t += 1; return true; } if (b <= c) return false; t += 1; return fun(a - b + c);}int main(){ int n; scanf("%d", &n); while (n -- ) { scanf("%d%d%d", &a, &b, &c); t = 0; bool res = fun(a); if (res) cout << t << endl; else cout << "fail" << endl; } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4104212 Created at: Wed Feb 09 2022 22:28:47 GMT+0800 (China Standard Time) Problem_id: 25\tTime: 27\tMemory: 3400*/#include <iostream>using namespace std;bool isprime(int x){ if (x < 2) return false; for (int i = 2; i <= x / i; i ++) if (x % i == 0) return false; return true;}int main(){ int T; scanf("%d", &T); while (T -- ) { int x; scanf("%d", &x); if(isprime(x)) puts("Yes"); else puts("No"); }}\n/* Author: 武迪 Result: AC\tSubmission_id: 4099484 Created at: Thu Jan 20 2022 01:18:19 GMT+0800 (China Standard Time) Problem_id: 26\tTime: 3\tMemory: 2088*/#include <stdio.h>#include <math.h>int main(){ double x,y,z,a,b,c,max,t;int n,i,k,maxi; while(scanf("%lf%lf%lf%d",&x,&y,&z,&n)==4){ max=0;maxi=1; for(i=0;i<n;i++){ scanf("%lf%lf%lf",&a,&b,&c); t=(a-x)*(a-x)+(b-y)*(b-y)+(c-z)*(c-z); if(t>max){max=t;maxi=i+1;} } scanf("%d",&k);printf("%d %lf\\n",maxi,k*2*sqrt(max)); }}\n/* Author: 武迪 Result: AC\tSubmission_id: 4099683 Created at: Thu Jan 20 2022 23:00:23 GMT+0800 (China Standard Time) Problem_id: 28\tTime: 4\tMemory: 3276*/#include <iostream>using namespace std;int valid(int x){ int n = x, sum = 0; while (n){ int r = n % 10; sum += r * r * r; n /= 10; } if (sum == x) return 1; return 0;}int main(){ int T; cin >> T; while (T --){ int a, b, exist = 0; cin >> a >> b; for ( int i = a; i <= b; i ++){ if (valid(i)) cout << i << ' ', exist = 1; } if(!exist) cout << -1 << endl; else cout << endl; } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4095285 Created at: Sat Jan 08 2022 00:47:14 GMT+0800 (China Standard Time) Problem_id: 30\tTime: 2\tMemory: 3456*/#include <iostream>using namespace std;int gcd(int n, int m){ int t; while (m != 0) { t = n % m; n = m; m = t; } return n;}int main(){ int T; scanf("%d", &T); while (T -- ) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); int e = a * d + c * b; int f = b * d; int r = gcd(e, f); cout << e / r << ' ' << f / r << endl; } return 0;}\n","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E10-2015%E7%BA%A7C++%E6%9C%9F%E6%9C%AB%E4%B8%8A%E6%9C%BA%E6%A8%A1%E6%8B%9F%E8%B5%9B/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E3-2015%E7%BA%A7C++%E7%AC%AC%E4%B8%89%E6%AC%A1%E7%BB%83%E4%B9%A0/","content":"/* Author: 武迪 Result: AC\tSubmission_id: 4098121 Created at: Wed Jan 12 2022 18:31:06 GMT+0800 (China Standard Time) Problem_id: 42\tTime: 11\tMemory: 3716*/#include <iostream>using namespace std;const int N = 1e6 + 10;int q[N], a[N], hh, tt;int main(){ int n; while (scanf("%d", &n) != EOF){ for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]); int res = -999998; hh = 0, tt = -1; for (int i = 0; i < n; i ++ ){ if (i == 0){ q[++tt] = a[i]; }else { while (hh <= tt && q[tt] < a[i]) tt--; // cout << q[hh] << endl; res = max(res, q[hh] - a[i]); q[++tt] = a[i]; } } printf("%d\\n", res); } return 0;}\n","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E4-2015%E7%BA%A7C++%E7%AC%AC%E5%9B%9B%E6%AC%A1%E7%BB%83%E4%B9%A0/","content":"/* Author: 武迪 Result: AC\tSubmission_id: 4099478 Created at: Thu Jan 20 2022 00:45:51 GMT+0800 (China Standard Time) Problem_id: 72\tTime: 2\tMemory: 3336*/#include <iostream>using namespace std;int main(){ int n; string s; while (cin >> n >> s){ int flag = 0; for (int i = 2; i <= n; i ++){ if (s[i] - s[i - 1] == 1 && s[i] - s[ i - 2] == 2) { flag = 1; break; } } if (flag) cout << "YES" << endl; else cout << "NO" << endl; } return 0;}\n/* Author: 武迪 Result: AC\tSubmission_id: 4104214 Created at: Wed Feb 09 2022 22:34:17 GMT+0800 (China Standard Time) Problem_id: 76\tTime: 15\tMemory: 3156*/#include <iostream>using namespace std;typedef long long LL;bool isprime(LL x){ if (x < 2) return false; for (int i = 2; i <= x / i; i ++) if (x % i == 0) return false; return true;}int main(){ LL x; while (cin >> x) { if (isprime(x)) cout << "jhljx is good!" << endl; else cout << "jhljx is sangxinbingkuang!" << endl; }}\n","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E5-2015%E7%BA%A7C++%E7%AC%AC%E4%BA%94%E6%AC%A1%E7%BB%83%E4%B9%A0/","content":"/* Author: 武迪 Result: AC\tSubmission_id: 4104225 Created at: Wed Feb 09 2022 23:05:23 GMT+0800 (China Standard Time) Problem_id: 92\tTime: 3\tMemory: 3280*/#include <iostream>#include <vector>using namespace std;typedef pair<int, int> PII;const int N = 1e6 + 10;void get_primes(int x){ vector<PII> primes; for (int i = 2; i <= x / i; i ++) { if (x % i == 0) { int r = 0; while (x % i == 0) x /= i, r ++; primes.push_back({i, r}); } } if (x > 1) primes.push_back({x, 1}); for (int i = 0; i < primes.size(); i ++) { int prime = primes[i].first, idx = primes[i].second; while(idx) { if(i == primes.size() - 1 && idx == 1) cout << prime; else cout << prime << '*'; idx --; } } puts("");}int main(){ int x; while (cin >> x) { if (x == 1) cout << x << endl; else get_primes(x); }}\n","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E6-2015%E7%BA%A7C++%E7%AC%AC%E5%85%AD%E6%AC%A1%E7%BB%83%E4%B9%A0%E8%B5%9B/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E7-2015%E7%BA%A7C++%E7%AC%AC%E4%B8%83%E6%AC%A1%E7%BB%83%E4%B9%A0%E8%B5%9B/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E8-2015%E7%BA%A7C++%E7%AC%AC%E5%85%AB%E6%AC%A1%E7%BB%83%E4%B9%A0%E8%B5%9B/","content":"/* Author: 武迪 Result: AC\tSubmission_id: 4095416 Created at: Sat Jan 08 2022 22:15:03 GMT+0800 (China Standard Time) Problem_id: 158\tTime: 10\tMemory: 3448*/#include <iostream>#include<vector>#include<algorithm>using namespace std;typedef pair<int, int> PII;int main(){ int n; while (scanf("%d", &n) != EOF) { vector<PII> segs; for (int i = 0; i < n; i ++ ) { int l, r; scanf("%d%d", &l, &r); segs.push_back({l, r}); } sort(segs.begin(), segs.end()); for (auto seg : segs) printf("%d %d\\n", seg.first, seg.second); } return 0;}\n","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/E9-2015%E7%BA%A7C++%E7%AC%AC%E4%B9%9D%E6%AC%A1%E7%BB%83%E4%B9%A0%E8%B5%9B/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"2015级-软件学院C++程序设计 - 第一次上机","url":"/2022/02/20/algorithm/oj4th/2015%E7%BA%A7-%E8%BD%AF%E4%BB%B6%E5%AD%A6%E9%99%A2-C++%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/Final-2015%E7%BA%A7C++%E6%9C%9F%E6%9C%AB%E4%B8%8A%E6%9C%BA/","content":"","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"Linux基础(四):shell语法","url":"/2022/02/21/ubuntu/Linux%E5%9F%BA%E7%A1%804_shell%E8%AF%AD%E6%B3%95/","content":"概论概论shell是我们通过命令行与操作系统沟通的语言。\nshell脚本可以直接在命令行中执行,也可以将一套逻辑组织成一个文件,方便复用。AC Terminal中的命令行可以看成是一个“shell脚本在逐行执行”。\nLinux中常见的shell脚本有很多种,常见的有:\n\nBourne Shell(/usr/bin/sh或/bin/sh)\nBourne Again Shell(/bin/bash)\nC Shell(/usr/bin/csh)\nK Shell(/usr/bin/ksh)\nzsh\n…Linux系统中一般默认使用bash,所以接下来讲解bash中的语法。文件开头需要写#! /bin/bash,指明bash为脚本解释器。\n\n学习技巧不要死记硬背,遇到含糊不清的地方,可以在Terminal里实际运行一遍。\n脚本示例新建一个test.sh文件,内容如下:#! /bin/bashecho \"Hello World!\"\n运行方式作为可执行文件acs@9e0ebfcd82d7:~$ chmod +x test.sh # 使脚本具有可执行权限acs@9e0ebfcd82d7:~$ ./test.sh # 当前路径下执行Hello World! # 脚本输出acs@9e0ebfcd82d7:~$ /home/acs/test.sh # 绝对路径下执行Hello World! # 脚本输出acs@9e0ebfcd82d7:~$ ~/test.sh # 家目录路径下执行Hello World! # 脚本输出用解释器执行acs@9e0ebfcd82d7:~$ bash test.shHello World! # 脚本输出\n注释单行注释每行中#之后的内容均是注释。# 这是一行注释echo 'Hello World' # 这也是注释\n多行注释格式::<<EOF第一行注释第二行注释第三行注释EOF其中EOF可以换成其它任意字符串。例如::<<abc第一行注释第二行注释第三行注释abc:<<!第一行注释第二行注释第三行注释!\n变量定义变量定义变量,不需要加$符号,例如:name1='yxc' # 单引号定义字符串name2=\"yxc\" # 双引号定义字符串name3=yxc # 也可以不加引号,同样表示字符串\n使用变量使用变量,需要加上$符号,或者${}符号。花括号是可选的,主要为了帮助解释器识别变量边界。name=yxcecho $name # 输出yxcecho ${name} # 输出yxcecho ${name}acwing # 输出yxcacwing\n只读变量使用readonly或者declare可以将变量变为只读。name=yxcreadonly namedeclare -r name # 两种写法均可name=abc # 会报错,因为此时name只读\n删除变量unset可以删除变量。name=yxcunset nameecho $name # 输出空行\n变量类型\n自定义变量(局部变量)子进程不能访问的变量\n环境变量(全局变量)子进程可以访问的变量\n\n自定义变量改成环境变量:acs@9e0ebfcd82d7:~$ name=yxc # 定义变量acs@9e0ebfcd82d7:~$ export name # 第一种方法acs@9e0ebfcd82d7:~$ declare -x name # 第二种方法\n环境变量改为自定义变量:acs@9e0ebfcd82d7:~$ export name=yxc # 定义环境变量acs@9e0ebfcd82d7:~$ declare +x name # 改为自定义变量\n字符串字符串可以用单引号,也可以用双引号,也可以不用引号。\n单引号与双引号的区别:\n\n单引号中的内容会原样输出,不会执行、不会取变量;\n双引号中的内容可以执行、可以取变量;name=yxc # 不用引号echo 'hello, $name \\\"hh\\\"' # 单引号字符串,输出 hello, $name \\\"hh\\\"echo \"hello, $name \\\"hh\\\"\" # 双引号字符串,输出 hello, yxc \"hh\"\n获取字符串长度name=\"yxc\"echo ${#name} # 输出3\n提取子串name=\"hello, yxc\"echo ${name:0:5} # 提取从0开始的5个字符\n默认变量\n\n文件参数变量在执行shell脚本时,可以向脚本传递参数。$1是第一个参数,$2是第二个参数,以此类推。特殊的,$0是文件名(包含路径)。例如:\n创建文件test.sh:#! /bin/bashecho \"文件名:\"$0echo \"第一个参数:\"$1echo \"第二个参数:\"$2echo \"第三个参数:\"$3echo \"第四个参数:\"$4然后执行该脚本:acs@9e0ebfcd82d7:~$ chmod +x test.sh acs@9e0ebfcd82d7:~$ ./test.sh 1 2 3 4文件名:./test.sh第一个参数:1第二个参数:2第三个参数:3第四个参数:4\n其它参数相关变量\n\n\n\n参数\n说明\n\n\n\n\n$#\n代表文件传入的参数个数,如上例中值为4\n\n\n$*\n由所有参数构成的用空格隔开的字符串,如上例中值为\"$1 $2 $3 $4\"\n\n\n$@\n每个参数分别用双引号括起来的字符串,如上例中值为\"$1\" \"$2\" \"$3\" \"$4\"\n\n\n\n脚本当前运行的进程ID\n\n\n$?\n上一条命令的退出状态(注意不是stdout,而是exit code)。0表示正常退出,其他值表示错误\n\n\n$(command)\n返回command这条命令的stdout(可嵌套)\n\n\n`command`\n返回command这条命令的stdout(不可嵌套)\n\n\n\n\n数组数组中可以存放多个不同类型的值,只支持一维数组,初始化时不需要指明数组大小。数组下标从0开始。\n定义数组用小括号表示,元素之间用空格隔开。例如:array=(1 abc \"def\" yxc)也可以直接定义数组中某个元素的值:array[0]=1array[1]=abcarray[2]=\"def\"array[3]=yxc\n读取数组中某个元素的值格式:${array[index]}例如:array=(1 abc \"def\" yxc)echo ${array[0]}echo ${array[1]}echo ${array[2]}echo ${array[3]}\n读取整个数组格式:${array[@]} # 第一种写法${array[*]} # 第二种写法例如:array=(1 abc \"def\" yxc)echo ${array[@]} # 第一种写法echo ${array[*]} # 第二种写法\n数组长度类似于字符串${#array[@]} # 第一种写法${#array[*]} # 第二种写法例如:array=(1 abc \"def\" yxc)echo ${#array[@]} # 第一种写法echo ${#array[*]} # 第二种写法\nexpr命令expr命令用于求表达式的值,格式为:expr 表达式表达式说明:\n\n用空格隔开每一项\n用反斜杠放在shell特定的字符前面(发现表达式运行错误时,可以试试转义)\n对包含空格和其他特殊字符的字符串要用引号括起来\nexpr会在stdout中输出结果。如果为逻辑关系表达式,则结果为真,stdout为1,否则为0。\nexpr的exit code:如果为逻辑关系表达式,则结果为真,exit code为0,否则为1。\n\n字符串表达式\nlength STRING返回STRING的长度\nindex STRING CHARSETCHARSET中任意单个字符在STRING中最前面的字符位置,下标从1开始。如果在STRING中完全不存在CHARSET中的字符,则返回0。\nsubstr STRING POSITION LENGTH返回STRING字符串中从POSITION开始,长度最大为LENGTH的子串。如果POSITION或LENGTH为负数,0或非数值,则返回空字符串。\n\n示例:str=\"Hello World!\"echo `expr length \"$str\"` # ``不是单引号,表示执行该命令,输出12echo `expr index \"$str\" aWd` # 输出7,下标从1开始echo `expr substr \"$str\" 2 3` # 输出 ell\n整数表达式expr支持普通的算术操作,算术表达式优先级低于字符串表达式,高于逻辑关系表达式。\n\n+ -加减运算。两端参数会转换为整数,如果转换失败则报错。\n\n* / %乘,除,取模运算。两端参数会转换为整数,如果转换失败则报错。\n\n() 可以该表优先级,但需要用反斜杠转义\n\n\n示例:a=3b=4echo `expr $a + $b` # 输出7echo `expr $a - $b` # 输出-1echo `expr $a \\* $b` # 输出12,*需要转义echo `expr $a / $b` # 输出0,整除echo `expr $a % $b` # 输出3echo `expr \\( $a + 1 \\) \\* \\( $b + 1 \\)` # 输出20,值为(a + 1) * (b + 1)\n逻辑关系表达式\n|如果第一个参数非空且非0,则返回第一个参数的值,否则返回第二个参数的值,但要求第二个参数的值也是非空或非0,否则返回0。如果第一个参数是非空或非0时,不会计算第二个参数。\n\n&如果两个参数都非空且非0,则返回第一个参数,否则返回0。如果第一个参为0或为空,则不会计算第二个参数。\n\n< <= = == != >= >比较两端的参数,如果为true,则返回1,否则返回0。”==”是”=”的同义词。”expr”首先尝试将两端参数转换为整数,并做算术比较,如果转换失败,则按字符集排序规则做字符比较。\n\n() 可以该表优先级,但需要用反斜杠转义\n\n\n示例:a=3b=4echo `expr $a \\> $b` # 输出0,>需要转义echo `expr $a '<' $b` # 输出1,也可以将特殊字符用引号引起来echo `expr $a '>=' $b` # 输出0echo `expr $a \\<\\= $b` # 输出1c=0d=5echo `expr $c \\& $d` # 输出0echo `expr $a \\& $b` # 输出3echo `expr $c \\| $d` # 输出5echo `expr $a \\| $b` # 输出3\nread命令read命令用于从标准输入中读取单行数据。当读到文件结束符时,exit code为1,否则为0。\n参数说明\n\n-p: 后面可以接提示信息\n-t:后面跟秒数,定义输入字符的等待时间,超过等待时间后会自动忽略此命令\n\n实例:acs@9e0ebfcd82d7:~$ read name # 读入name的值acwing yxc # 标准输入acs@9e0ebfcd82d7:~$ echo $name # 输出name的值acwing yxc #标准输出acs@9e0ebfcd82d7:~$ read -p \"Please input your name: \" -t 30 name # 读入name的值,等待时间30秒Please input your name: acwing yxc # 标准输入acs@9e0ebfcd82d7:~$ echo $name # 输出name的值acwing yxc # 标准输出\necho命令echo用于输出字符串。命令格式:echo STRING\n显示普通字符串echo \"Hello AC Terminal\"echo Hello AC Terminal # 引号可以省略\n显示转义字符echo \"\\\"Hello AC Terminal\\\"\" # 注意只能使用双引号,如果使用单引号,则不转义echo \\\"Hello AC Terminal\\\" # 也可以省略双引号\n显示变量name=yxcecho \"My name is $name\" # 输出 My name is yxc\n显示换行echo -e \"Hi\\n\" # -e 开启转义echo \"acwing\"\n输出结果:Hiacwing\n显示不换行echo -e \"Hi \\c\" # -e 开启转义 \\c 不换行echo \"acwing\"\n输出结果:Hi acwing\n显示结果定向至文件echo \"Hello World\" > output.txt # 将内容以覆盖的方式输出到output.txt中\n原样输出字符串,不进行转义或取变量(用单引号)name=acwingecho '$name\\\"'\n输出结果$name\\\"\n显示命令的执行结果echo `date`\n输出结果:Wed Sep 1 11:45:33 CST 2021\nprintf命令printf命令用于格式化输出,类似于C/C++中的printf函数。\n默认不会在字符串末尾添加换行符。\n命令格式:printf format-string [arguments...]\n用法示例脚本内容:printf \"%10d.\\n\" 123 # 占10位,右对齐printf \"%-10.2f.\\n\" 123.123321 # 占10位,保留2位小数,左对齐printf \"My name is %s\\n\" \"yxc\" # 格式化输出字符串printf \"%d * %d = %d\\n\" 2 3 `expr 2 \\* 3` # 表达式的值作为参数输出结果: 123.123.12 .My name is yxc2 * 3 = 6\ntest命令与判断符号[]逻辑运算符&&和||\n&& 表示与,|| 表示或\n二者具有短路原则:expr1 && expr2:当expr1为假时,直接忽略expr2expr1 || expr2:当expr1为真时,直接忽略expr2\n表达式的exit code为0,表示真;为非零,表示假。(与C/C++中的定义相反)test命令\n\n在命令行中输入man test,可以查看test命令的用法。\ntest命令用于判断文件类型,以及对变量做比较。\ntest命令用exit code返回结果,而不是使用stdout。0表示真,非0表示假。\n例如:test 2 -lt 3 # 为真,返回值为0echo $? # 输出上个命令的返回值,输出0acs@9e0ebfcd82d7:~$ ls # 列出当前目录下的所有文件homework output.txt test.sh tmpacs@9e0ebfcd82d7:~$ test -e test.sh && echo \"exist\" || echo \"Not exist\"exist # test.sh 文件存在acs@9e0ebfcd82d7:~$ test -e test2.sh && echo \"exist\" || echo \"Not exist\"Not exist # testh2.sh 文件不存在\n文件类型判断命令格式:test -e filename # 判断文件是否存在|测试参数 |代表意义||—|—||-e |文件是否存在||-f |是否为文件||-d |是否为目录|\n文件权限判断命令格式:test -r filename # 判断文件是否可读|测试参数 |代表意义||—|—||-r |文件是否可读||-w |文件是否可写||-x |文件是否可执行||-s |是否为非空文件|\n整数间的比较命令格式:test $a -eq $b # a是否等于b|测试参数| 代表意义||—|—||-eq |a是否等于b||-ne |a是否不等于b||-gt |a是否大于b||-lt |a是否小于b||-ge |a是否大于等于b||-le |a是否小于等于b|\n字符串比较\n\n\n\n测试参数\n代表意义\n\n\n\n\ntest -z STRING\n判断STRING是否为空,如果为空,则返回true\n\n\ntest -n STRING\n判断STRING是否非空,如果非空,则返回true(-n可以省略)\n\n\ntest str1 == str2\n判断str1是否等于str2\n\n\ntest str1 != str2\n判断str1是否不等于str2\n\n\n\n\n多重条件判定命令格式:test -r filename -a -x filename|测试参数| 代表意义||—|—||-a |两条件是否同时成立||-o |两条件是否至少一个成立||! |取反。如 test ! -x file,当file不可执行时,返回true|\n判断符号[][]与test用法几乎一模一样,更常用于if语句中。另外[[]]是[]的加强版,支持的特性更多。\n例如:[ 2 -lt 3 ] # 为真,返回值为0echo $? # 输出上个命令的返回值,输出0acs@9e0ebfcd82d7:~$ ls # 列出当前目录下的所有文件homework output.txt test.sh tmpacs@9e0ebfcd82d7:~$ [ -e test.sh ] && echo \"exist\" || echo \"Not exist\"exist # test.sh 文件存在acs@9e0ebfcd82d7:~$ [ -e test2.sh ] && echo \"exist\" || echo \"Not exist\"Not exist # testh2.sh 文件不存在注意:\n\n[]内的每一项都要用空格隔开\n中括号内的变量,最好用双引号括起来\n中括号内的常数,最好用单或双引号括起来例如:name=\"acwing yxc\"[ $name == \"acwing yxc\" ] # 错误,等价于 [ acwing yxc == \"acwing yxc\" ],参数太多[ \"$name\" == \"acwing yxc\" ] # 正确\n判断语句if…then形式\n\n类似于C/C++中的if-else语句。\n单层if命令格式:if conditionthen 语句1 语句2 ...fi示例:a=3b=4if [ \"$a\" -lt \"$b\" ] && [ \"$a\" -gt 2 ]then echo ${a}在范围内fi输出结果:3在范围内\n单层if-else命令格式if conditionthen 语句1 语句2 ...else 语句1 语句2 ...fi示例:a=3b=4if ! [ \"$a\" -lt \"$b\" ]then echo ${a}不小于${b}else echo ${a}小于${b}fi输出结果:3小于4\n多层if-elif-elif-else命令格式if conditionthen 语句1 语句2 ...elif conditionthen 语句1 语句2 ...elif conditionthen 语句1 语句2else 语句1 语句2 ...fi示例:a=4if [ $a -eq 1 ]then echo ${a}等于1elif [ $a -eq 2 ]then echo ${a}等于2elif [ $a -eq 3 ]then echo ${a}等于3else echo 其他fi输出结果:其他\ncase…esac形式类似于C/C++中的switch语句。\n命令格式case $变量名称 in 值1) 语句1 语句2 ... ;; # 类似于C/C++中的break 值2) 语句1 语句2 ... ;; *) # 类似于C/C++中的default 语句1 语句2 ... ;;esac示例:a=4case $a in 1) echo ${a}等于1 ;; 2) echo ${a}等于2 ;; 3) echo ${a}等于3 ;; *) echo 其他 ;; esac输出结果:其他\n循环语句for…in…do…done命令格式:for var in val1 val2 val3do 语句1 语句2 ...done示例1,输出a 2 cc,每个元素一行:for i in a 2 ccdo echo $idone示例2,输出当前路径下的所有文件名,每个文件名一行:for file in `ls`do echo $filedone示例3,输出1-10for i in $(seq 1 10)do echo $idone示例4,使用{1..10} 或者 {a..z}for i in {a..z}do echo $idone\nfor ((…;…;…)) do…done命令格式:for ((expression; condition; expression))do 语句1 语句2done示例,输出1-10,每个数占一行:for ((i=1; i<=10; i++))do echo $idone\nwhile…do…done循环命令格式:while conditiondo 语句1 语句2 ...done示例,文件结束符为Ctrl+d,输入文件结束符后read指令返回false。while read namedo echo $namedone\nuntil…do…done循环当条件为真时结束。\n命令格式:until conditiondo 语句1 语句2 ...done示例,当用户输入yes或者YES时结束,否则一直等待读入。until [ \"${word}\" == \"yes\" ] || [ \"${word}\" == \"YES\" ]do read -p \"Please input yes/YES to stop this program: \" worddone\nbreak命令跳出当前一层循环,注意与C/C++不同的是:break不能跳出case语句。\n示例while read namedo for ((i=1;i<=10;i++)) do case $i in 8) break ;; *) echo $i ;; esac donedone该示例每读入非EOF的字符串,会输出一遍1-7。该程序可以输入Ctrl+d文件结束符来结束,也可以直接用Ctrl+c杀掉该进程。\ncontinue命令跳出当前循环。\n示例:for ((i=1;i<=10;i++))do if [ `expr $i % 2` -eq 0 ] then continue fi echo $idone该程序输出1-10中的所有奇数。\n死循环的处理方式如果Terminal可以打开该程序,则输入Ctrl+c即可。\n否则可以直接关闭进程:\n\n使用top命令找到进程的PID\n输入kill -9 PID即可关掉此进程\n\n函数bash中的函数类似于C/C++中的函数,但return的返回值与C/C++不同,返回的是exit code,取值为0-255,0表示正常结束。\n如果想获取函数的输出结果,可以通过echo输出到stdout中,然后通过$(function_name)来获取stdout中的结果。\n函数的return值可以通过$?来获取。\n命令格式:[function] func_name() { # function关键字可以省略 语句1 语句2 ...}\n不获取 return值和stdout值示例func() { name=yxc echo \"Hello $name\"}func输出结果:Hello yxc\n获取 return值和stdout值不写return时,默认return 0。\n示例func() { name=yxc echo \"Hello $name\" return 123}output=$(func)ret=$?echo \"output = $output\"echo \"return = $ret\"输出结果:output = Hello yxcreturn = 123\n函数的输入参数在函数内,$1表示第一个输入参数,$2表示第二个输入参数,依此类推。\n注意:函数内的$0仍然是文件名,而不是函数名。\n示例:func() { # 递归计算 $1 + ($1 - 1) + ($1 - 2) + ... + 0 word=\"\" while [ \"${word}\" != 'y' ] && [ \"${word}\" != 'n' ] do read -p \"要进入func($1)函数吗?请输入y/n:\" word done if [ \"$word\" == 'n' ] then echo 0 return 0 fi if [ $1 -le 0 ] then echo 0 return 0 fi sum=$(func $(expr $1 - 1)) echo $(expr $sum + $1)}echo $(func 10)输出结果:55\n函数内的局部变量可以在函数内定义局部变量,作用范围仅在当前函数内。\n可以在递归函数中定义局部变量。\n命令格式:local 变量名=变量值例如:#! /bin/bashfunc() { local name=yxc echo $name}funcecho $name输出结果:yxc第一行为函数内的name变量,第二行为函数外调用name变量,会发现此时该变量不存在。\nexit命令exit命令用来退出当前shell进程,并返回一个退出状态;使用$?可以接收这个退出状态。\nexit命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。\nexit退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。\n示例:\n创建脚本test.sh,内容如下:#! /bin/bashif [ $# -ne 1 ] # 如果传入参数个数等于1,则正常退出;否则非正常退出。then echo \"arguments not valid\" exit 1else echo \"arguments valid\" exit 0fi执行该脚本:acs@9e0ebfcd82d7:~$ chmod +x test.sh acs@9e0ebfcd82d7:~$ ./test.sh acwingarguments validacs@9e0ebfcd82d7:~$ echo $? # 传入一个参数,则正常退出,exit code为00acs@9e0ebfcd82d7:~$ ./test.sh arguments not validacs@9e0ebfcd82d7:~$ echo $? # 传入参数个数不是1,则非正常退出,exit code为11\n文件重定向每个进程默认打开3个文件描述符:\n\nstdin标准输入,从命令行读取数据,文件描述符为0\nstdout标准输出,向命令行输出数据,文件描述符为1\nstderr标准错误输出,向命令行输出数据,文件描述符为2可以用文件重定向将这三个文件重定向到其他文件中。\n\n重定向命令列表\n\n\n\n命令\n说明\n\n\n\n\ncommand > file\n将tdout重定向到file中\n\n\ncommand < file\n将stdin重定向到file中\n\n\ncommand >> file\n将stdout以追加方式重定向到file中\n\n\ncommand n> file\n将文件描述符n重定向到file中\n\n\ncommand n>> file\n将文件描述符n以追加方式重定向到file中\n\n\n\n\n输入和输出重定向echo -e \"Hello \\c\" > output.txt # 将stdout重定向到output.txt中echo \"World\" >> output.txt # 将字符串追加到output.txt中read str < output.txt # 从output.txt中读取字符串echo $str # 输出结果:Hello World\n同时重定向stdin和stdout创建bash脚本:#! /bin/bashread aread becho $(expr \"$a\" + \"$b\")创建input.txt,里面的内容为:34执行命令:acs@9e0ebfcd82d7:~$ chmod +x test.sh # 添加可执行权限acs@9e0ebfcd82d7:~$ ./test.sh < input.txt > output.txt # 从input.txt中读取内容,将输出写入output.txt中acs@9e0ebfcd82d7:~$ cat output.txt # 查看output.txt中的内容7\n引入外部脚本类似于C/C++中的include操作,bash也可以引入其他文件中的代码。\n语法格式:. filename # 注意点和文件名之间有一个空格或source filename示例\n创建test1.sh,内容为:#! /bin/bashname=yxc # 定义变量name然后创建test2.sh,内容为:#! /bin/bashsource test1.sh # 或 . test1.shecho My name is: $name # 可以使用test1.sh中的变量执行命令:acs@9e0ebfcd82d7:~$ chmod +x test2.sh acs@9e0ebfcd82d7:~$ ./test2.sh My name is: yxc\n","categories":["教程"],"tags":["Linux","shell"]},{"title":"2021级《C语言程序设计基础题解与实训指南》专项练习","url":"/2022/02/20/algorithm/oj4th/2021%E7%BA%A7-%E3%80%8AC%E8%AF%AD%E8%A8%80%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E5%9F%BA%E7%A1%80%E9%A2%98%E8%A7%A3%E4%B8%8E%E5%AE%9E%E8%AE%AD%E6%8C%87%E5%8D%97%E3%80%8B%E4%B8%93%E9%A1%B9%E7%BB%83%E4%B9%A0/","content":"专项练习1: 基本数据处理A 题2-1 简单字符(串)输出:颜文字表情图案绘制/* Author: wudi Result: AC\tSubmission_id: 4098725 Created at: Sun Jan 16 2022 16:59:21 GMT+0800 (China Standard Time) Problem_id: 4542\tTime: 1\tMemory: 1460*/#include <stdio.h>int main(){ printf("\\"\\\\(^_^ )/\\""); return 0;}\nB 题2-2 简单字符(串)输出:转义符应用/* Author: wudi Result: AC\tSubmission_id: 4098726 Created at: Sun Jan 16 2022 17:00:54 GMT+0800 (China Standard Time) Problem_id: 4543\tTime: 1\tMemory: 1396*/#include <stdio.h>int main(){ printf("? *&\\\\! _//\\\\a@\\\\\\\\\\\\r\\\\n! //\\\\\\\\\\"_\\"/\\\\\\\\^! ~zZ"); return 0;}\nC 题2-3 基本输入输出及运算:数的向上取整/* Author: wudi Result: AC\tSubmission_id: 4098730 Created at: Sun Jan 16 2022 17:03:59 GMT+0800 (China Standard Time) Problem_id: 4544\tTime: 7\tMemory: 1640*/#include <stdio.h>int main(){ int n, m; scanf("%d%d", &n ,&m); int r = n / m; if (r * m == n) printf("%d", r); else printf("%d", r + 1); return 0;}\nD 题2-4 基本输入输出及运算:计算预期收益/* Author: wudi Result: AC\tSubmission_id: 4098733 Created at: Sun Jan 16 2022 17:09:28 GMT+0800 (China Standard Time) Problem_id: 4545\tTime: 2\tMemory: 1716*/#include <stdio.h>int main(){ float a, c; scanf("%f%f", &a, &c); double s = a * (1 + c / 100); printf("%.2f", s); return 0;}\nE 题2-5 基本输入输出及运算:计算平均值/* Author: wudi Result: AC\tSubmission_id: 4098740 Created at: Sun Jan 16 2022 17:23:59 GMT+0800 (China Standard Time) Problem_id: 4546\tTime: 0\tMemory: 1688*/#include <stdio.h>int main(){ float a, b, c; scanf("%f%f%f", &a, &b, &c); float s = (a + b + c) / 3; printf("%.1f", s); return 0;}\nF 题2-6 基本输入输出及运算:计算圆柱体表面积/* Author: wudi Result: AC\tSubmission_id: 4098745 Created at: Sun Jan 16 2022 17:29:00 GMT+0800 (China Standard Time) Problem_id: 4547\tTime: 2\tMemory: 1668*/#include <stdio.h>int main(){ float r, h; float pi = 3.14; scanf("%f%f", &r, &h); float area = 2 * pi * r * h + pi * r * r * 2; printf("Area = %.3f", area); return 0;}\nG 题2-7 模运算:简单取模操作/* Author: wudi Result: AC\tSubmission_id: 4098758 Created at: Sun Jan 16 2022 19:06:24 GMT+0800 (China Standard Time) Problem_id: 4548\tTime: 6\tMemory: 1700*/#include <stdio.h>int main(){ unsigned long long n; scanf("%llu", &n); long long res = (3 * n + 1) % 100000007; printf("%llu", res); return 0;}\nH 题2-8 模运算:数的按位拆分/* Author: wudi Result: AC\tSubmission_id: 4098759 Created at: Sun Jan 16 2022 19:11:14 GMT+0800 (China Standard Time) Problem_id: 4549\tTime: 2\tMemory: 1592*/#include <stdio.h>int main(){ int n; scanf("%d", &n); int L = 0, i = 1; while (n){ int r = n % 10; n /= 10; L += i * r; i ++; } printf("%d", L); return 0;}\nI 题2-9 模运算:数位翻转/* Author: wudi Result: AC\tSubmission_id: 4098770 Created at: Sun Jan 16 2022 19:59:59 GMT+0800 (China Standard Time) Problem_id: 4550\tTime: 3\tMemory: 1728*/#include <stdio.h>int main(){ int n; scanf("%d", &n); int l = n / 10000 * 10000; n %= 10000; int i = 1000, last = 0; while (n){ int r = n % 10; last += i * r; n /= 10;; i /= 10; } printf("%d", l + last); return 0;}\nJ 题2-10 模运算:学号识别码/* Author: wudi Result: AC\tSubmission_id: 4098773 Created at: Sun Jan 16 2022 20:10:04 GMT+0800 (China Standard Time) Problem_id: 4551\tTime: 2\tMemory: 1692*/#include <stdio.h>int main(){ int n; scanf("%d", &n); int i = 2, res = 0, raw = n; while (n){ int r = n % 10; res += i * r; n /= 10; i ++; } printf("%d", raw * 10 + res % 10); return 0;}\nK 题2-11 模运算:队列找字母/* Author: wudi Result: AC\tSubmission_id: 4098777 Created at: Sun Jan 16 2022 20:23:15 GMT+0800 (China Standard Time) Problem_id: 4552\tTime: 2\tMemory: 1544*/#include <stdio.h>int main(){ char s[7] = "abcdefg"; int n; scanf("%d", &n); printf("%c", s[n % 7 - 1]); return 0;}\nL 题2-12 模运算:火仙草数/* Author: wudi Result: AC\tSubmission_id: 4098777 Created at: Sun Jan 16 2022 20:23:15 GMT+0800 (China Standard Time) Problem_id: 4552\tTime: 2\tMemory: 1544*/#include <stdio.h>int main(){ char s[7] = "abcdefg"; int n; scanf("%d", &n); printf("%c", s[n % 7 - 1]); return 0;}\nM 题2-13 数据类型转换:分数转小数/* Author: wudi Result: AC\tSubmission_id: 4098827 Created at: Sun Jan 16 2022 22:08:30 GMT+0800 (China Standard Time) Problem_id: 4554\tTime: 1\tMemory: 1640*/#include <stdio.h>int main(){ int a, b; scanf("%d/%d", &a, &b); double res = a; res /= b; printf("%.2f", res); return 0;}\nN 题2-14 位运算:A op B Problem/* Author: wudi Result: AC\tSubmission_id: 4098825 Created at: Sun Jan 16 2022 21:55:18 GMT+0800 (China Standard Time) Problem_id: 4555\tTime: 119\tMemory: 1664*/#include <stdio.h>int main(){ int q; scanf("%lld", &q); while (q --){ unsigned int a, b; scanf("%u%u", &a, &b); // printf("%lld %lld\\n", a, b); int w0, w1, w2, w3; scanf("%u%u%u%u", &w0, &w1, &w2, &w3); int c = 0; unsigned long long res = 0; for(int i = 31; i >= 0; i --){ int a0 = a >> i & 1; int b0 = b >> i & 1; if (a0 == 0 && b0 == 0) c = w0; if (a0 == 0 && b0 == 1) c = w1; if (a0 == 1 && b0 == 0) c = w2; if (a0 == 1 && b0 == 1) c = w3; res += c << i; } if(q) printf("%u\\n", res); else printf("%u", res); } return 0;}\n专项练习2: 结构化编程(❌)J, M未完成\nA 题3-1 逻辑表达式的应用:名次预测/* Author: wudi Result: AC\tSubmission_id: 4098828 Created at: Sun Jan 16 2022 22:20:01 GMT+0800 (China Standard Time) Problem_id: 4556\tTime: 6\tMemory: 1704*/#include <stdio.h>int main(){ int i = 1, cnt = 0; while (i <= 6){ int n; scanf("%d", &n); if (n == i) cnt ++; i ++; } if (cnt == 0) printf("Sorry!Unlucky!"); else{ while (cnt --) printf("*"); } return 0;}\nB 题3-2 单分支选择结构:寻找第二小数/* Author: wudi Result: AC\tSubmission_id: 4098829 Created at: Sun Jan 16 2022 22:28:09 GMT+0800 (China Standard Time) Problem_id: 4557\tTime: 1\tMemory: 1664*/#include <stdio.h>int main(){ int a, b, c; scanf("%d%d%d", &a, &b, &c); if ( a >= b){ int temp = a; a = b; b = temp; } if (b >= c){ int temp = b; b = c; c = temp; } if (a >= b) printf("%d", a); else printf("%d", b); return 0;}\nC 题3-3 单分支选择结构:重逢时刻/* Author: wudi Result: AC\tSubmission_id: 4099087 Created at: Tue Jan 18 2022 12:41:36 GMT+0800 (China Standard Time) Problem_id: 4558\tTime: 20\tMemory: 1720*/#include <stdio.h>int main(){ int n; scanf("%d", &n); n %= 12; int hh, mm; double ss; if (n == 0 || n == 11){ hh = 0; mm = 0; ss = 0.0; } else { double t = n + n / 11.0; hh = t; mm = (t - hh) * 60; ss = t * 3600 - hh * 3600 - mm * 60; } printf("%d:%d:%.7f\\n", hh, mm, ss); return 0;}\nD 题3-4 单分支选择结构:方程求解/* Author: wudi Result: AC\tSubmission_id: 4099119 Created at: Tue Jan 18 2022 14:17:48 GMT+0800 (China Standard Time) Problem_id: 4559\tTime: 7\tMemory: 2128*/#include <stdio.h>#include <math.h>int main(){ long long a, b, c; while (scanf("%lld%lld%lld", &a, &b, &c) != EOF){ if (a && b){ if (b * b > 4 * a * c){ double x1 = 2.0 * a / (-1.0 * b + sqrt(1.0 * b * b - 4.0 * a * c)); double x2 = 2.0 * a / (-1.0 * b - sqrt(1.0 * b * b - 4.0 * a * c)); if (x1 > x2) printf("%.2lf %.2lf\\n", x2, x1); else printf("%.2lf %.2lf\\n", x1, x2); } else if (b * b == 4 * a * c){ double x = (2.0 * a) / (-1.0 * b); printf("%.2lf\\n", x); } else printf("NO Solution\\n"); } else if (!a && b){ double x = - 1.00 * b / c; printf("%.2lf\\n", x); } else if (a && !b){ if (c > 0) printf("NO Solution\\n"); else { double x1 = sqrt(-1.00 * a / c); double x2 = -1.00 * sqrt(-1.00 * a / c); printf("%.2lf %.2lf\\n", x2, x1); } } else if (!a && !b){ printf("NO Solution\\n"); } } return 0;}\nE 题3-5 双分支选择结构:直线与圆/* Author: wudi Result: AC\tSubmission_id: 4099132 Created at: Tue Jan 18 2022 15:06:35 GMT+0800 (China Standard Time) Problem_id: 4560\tTime: 8\tMemory: 2076*/#include <stdio.h>#include <math.h>int main(){ double x1, y1, x2, y2, x3, y3, r; double a, b, c, l; while (scanf("%lf%lf%lf%lf%lf%lf%lf", &x1, &y1, &x2, &y2, &x3, &y3, &r) != EOF){ // printf("%lf %lf %lf %lf %lf %lf %lf\\n",x1, y1, x2, y2, x3, y3, r); if (x1 == x2 && y1 != y2){ l = fabs(x3 - x1); } else if (x1 != x2 && y1 == y2){ l = fabs(y3 - y1); } else if (x1 == x2 && y1 == y2){ l = sqrt((x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1)); } else if (x1 != x2 && y1 != y2){ a = (y1 - y2) / (x1 - x2); b = - 1.00; c = (x1 * y2 - x2 * y1) / (x1 - x2); l = fabs(a * x3 + b * y3 + c) / (sqrt(a * a + b * b)); } // printf("%lf %lf\\n", l, r); if (l < r) printf("2\\n"); else if (l == r) printf("1\\n"); else printf("0\\n"); } return 0;}\nF 题3-6 双分支选择结构:温度转换/* Author: wudi Result: AC\tSubmission_id: 4099145 Created at: Tue Jan 18 2022 15:45:06 GMT+0800 (China Standard Time) Problem_id: 4561\tTime: 7\tMemory: 1744*/#include <stdio.h>double floor(double x){ int res = x * 100; if (res % 10 < 5){ res /= 10; x = res / 10.0; } else { res = res / 10 + 1; x = res / 10.0; } return x;}int main(){ int n1, res; double n2; char T1, T2; scanf("<%d><%c>", &n1, &T1); if (T1 == 'C') { T2 = 'F'; n2 = n1 * 9.00 / 5.00 + 32.0; } else if (T1 == 'F'){ T2 = 'C'; n2 = (n1 - 32.0) * (5.00 / 9.00); } // printf("%lf\\n", n2); if (n2 > 0) n2 = floor(n2); else n2 = -1.0 * floor(-1.0 * n2); printf("<%d><%c>=<%.1lf><%c>", n1, T1, n2, T2); return 0;}\nG 题3-7 双分支选择结构:统计阶乘的尾数0/* Author: wudi Result: AC\tSubmission_id: 4099164 Created at: Tue Jan 18 2022 16:23:48 GMT+0800 (China Standard Time) Problem_id: 4562\tTime: 13\tMemory: 1732*/#include <stdio.h>int cntZero(int n){ int sum = 0; if (n == 0) return 0; else { while (n){ sum += n / 5; n /= 5; } } return sum;}int main(){ int n, cnt = 0; scanf("%d", &n); for (int i = 0; i <= n; i ++){ int num = cntZero(i); // printf("%i : %d\\n",i, num); if (num % 2 == 0) cnt ++; } printf("%d", cnt); return 0;}\nH 题3-8 双分支选择结构:字符大小写转换/* Author: wudi Result: AC\tSubmission_id: 4099176 Created at: Tue Jan 18 2022 16:36:23 GMT+0800 (China Standard Time) Problem_id: 4563\tTime: 6\tMemory: 1692*/#include <stdio.h>const int N = 100010;int main(){ char link[N], pwd[N]; scanf("%s", link); scanf("%s", pwd); for (int i = 0; link[i]; i ++){ if (link[i] - 'Z' <= 0 && link[i] - 'A' >= 0){ // 为大写字母 link[i] = link[i] - 'A' + 'a'; } else if (link[i] - 'z' <= 0 && link[i] - 'a' >= 0){ // 为小写字母 link[i] = link[i] -'a' + 'A'; } printf("%c", link[i]); } printf("\\n"); for (int i = 0; pwd[i]; i ++){ if (pwd[i] - 'Z' <= 0 && pwd[i] - 'A' >= 0){ // 为大写字母 pwd[i] = pwd[i] - 'A' + 'a'; } else if (pwd[i] - 'z' <= 0 && pwd[i] - 'a' >= 0){ // 为小写字母 pwd[i] = pwd[i] -'a' + 'A'; } printf("%c", pwd[i]); } return 0;}\nI 题3-9 多分支条件语句:求解分段函数/* Author: wudi Result: AC\tSubmission_id: 4099178 Created at: Tue Jan 18 2022 16:39:28 GMT+0800 (China Standard Time) Problem_id: 4564\tTime: 3\tMemory: 1684*/#include <stdio.h>int main(){ long long x, y; scanf("%lld%lld", &x, &y); if (x < 1) y = x; else if (x >= 1 && x < 10) y = 2 * x - 3; else if (x >= 10) y = 3 * x - 5; printf("%lld", y); return 0;}\nJ 题3-10 多分支条件语句:窗口的嵌套(❌)K 题3-11 多路选择的switch语句:简单计算器/* Author: wudi Result: AC\tSubmission_id: 4099252 Created at: Tue Jan 18 2022 21:00:28 GMT+0800 (China Standard Time) Problem_id: 4566\tTime: 1\tMemory: 1700*/#include <stdio.h>double floor(double x){ if (x < 0) return -1.0 * floor(-1.0 * x); int res = x * 1000; if (res % 10 < 5){ res /= 10; x = res / 100.0; } else { res = res / 10 + 1; x = res / 100.0; } return x;}int main(){ char op; double x, y, res; scanf("%c", &op); scanf("%lf", &x); scanf("%lf", &y); if (op == '+'){ res = x + y; } else if (op == '-'){ res = x - y; } else if (op == '*'){ res = x * y; } else if (op == '/'){ if (y != 0) res = x / y; } if (y == 0 && op == '/'){ printf("invalidexpression"); }else { // res = floor(res); printf("%.2lf", res); } return 0;}\nL 题3-12 选择结构的嵌套:交换生条件审核/* Author: wudi Result: AC\tSubmission_id: 4099265 Created at: Tue Jan 18 2022 22:23:03 GMT+0800 (China Standard Time) Problem_id: 4567\tTime: 2\tMemory: 1744*/#include <stdio.h>double avg(double a, double b, double c){ return (a + b + c) / 3.0;}int main(){ int flag; double gpa; double a1, b1, c1, a2, b2, c2; scanf("%d%lf", &flag, &gpa); scanf("%lf%lf%lf", &a1, &b1, &c1); scanf("%lf%lf%lf", &a2, &b2, &c2); if(flag){ if (gpa >= 3.5) printf("APPROVED"); else if (avg(a1, b1, c1) >= 80 && avg(a2, b2, c2) >= 80) printf("APPROVED"); else printf("REJECTED"); } else { if (gpa >= 3.6) printf("APPROVED"); else if (avg(a1, b1, c1) > 85 && avg(a2, b2, c2) > 85) printf("APPROVED"); else printf("REJECTED"); } return 0;}\nM 题3-13 选择结构的嵌套:观影计划(❌)不会写\nN 题3-14 多路分支选择结构:方向判断/* Author: wudi Result: AC\tSubmission_id: 4104410 Created at: Thu Feb 10 2022 21:53:28 GMT+0800 (China Standard Time) Problem_id: 4569\tTime: 23\tMemory: 2384*/#include <stdio.h>#include <math.h>const double pi = 3.14159265;int main(){ int x, y; scanf("%d%d", &x, &y); if(x == 0 && y == 0) printf("Bingo\\n"); else if (x == 0 || y == 0) { if (y == 0) { if (x > 0) printf("E\\n"); else printf("W\\n"); } else { if (y > 0) printf("N\\n"); else printf("S\\n"); } } else { double deg = atan(abs(x) * 1.0 / abs(y)) * 180 / pi; if (x > 0 && y > 0) printf("NE%.2lf", deg); if (x > 0 && y < 0) printf("SE%.2lf", deg); if (x < 0 && y > 0) printf("NW%.2lf", deg); if (x < 0 && y < 0) printf("SW%.2lf", deg); } return 0;}\nO 题3-15 while循环(计数器控制):判断2的幂次数/* Author: wudi Result: AC\tSubmission_id: 4104229 Created at: Wed Feb 09 2022 23:18:56 GMT+0800 (China Standard Time) Problem_id: 4570\tTime: 843\tMemory: 1652*/#include <stdio.h>typedef unsigned long long ULL;ULL lowbit(ULL x) // 返回末尾的1{ return x & -x;}int main(){ int T; scanf("%d", &T); while (T -- ) { ULL x; scanf("%llu", &x); int res = 0; while (x) x -= lowbit(x), res ++; if (res == 1) printf("222\\n"); else printf("%d\\n", res); }}\nP 题3-16 while循环(标志控制):破译密码/* Author: wudi Result: AC\tSubmission_id: 4104234 Created at: Wed Feb 09 2022 23:28:57 GMT+0800 (China Standard Time) Problem_id: 4571\tTime: 5\tMemory: 1612*/#include <stdio.h>int main(){ char s[110]; scanf("%s", s); for (int i = 0; s[i]; i ++) { s[i] += 4; } printf("%s", s);}\nQ 题3-17 dowhile循环(标志控制):士兵站队/* Author: wudi Result: AC\tSubmission_id: 4104415 Created at: Thu Feb 10 2022 22:01:06 GMT+0800 (China Standard Time) Problem_id: 4572\tTime: 3\tMemory: 1732*/#include <stdio.h>int main(){ int a, b, c, x, y, z; scanf("%d%d", &a, &x); scanf("%d%d", &b, &y); scanf("%d%d", &c, &z); int n = 1; do n ++; while(n % a != x || n % b != y || n % c != z); printf("%d\\n", n); return 0;}\nR 题3-18 for循环(计数器控制):日历计算/* Author: wudi Result: AC\tSubmission_id: 4105552 Created at: Tue Feb 15 2022 23:33:09 GMT+0800 (China Standard Time) Problem_id: 4573\tTime: 10\tMemory: 1664*/#include <stdio.h>int Day(int yy, int mm, int dd){ int month[] = {31,28,31,30,31,30,31,31,30,31,30,31}; int n1 = yy / 4 - yy / 100 + yy / 400; int n2 = 1900 / 4 - 1900 / 100 + 1900 / 400; n1 -= n2; if (yy % 400 == 0 || yy % 100 != 0 && yy % 4 == 0) month[1] = 29, n1 --; for (int i = 1; i < mm; i ++ ) dd += month[i - 1]; return 365 * (yy - 1900) + n1 + dd;}int main(){ int m, n; scanf("%d%d", &m, &n); int month[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; if (m % 400 == 0 || m % 100 != 0 && m % 4 == 0) month[1] = 29; // 计算天数 int days = Day(m, n, 1); // 计算n月1日是周几 int week = days % 7; // printf("weeks:%d\\n", week); printf(" Sun Mon Tue Wed Thu Fri Sat\\n"); for(int i = 0; i < week; i ++) printf(" "); for (int i = 1; i <= month[n - 1]; i ++ ) { printf(" %3d", i); if ((i+ week) % 7 == 0) printf("\\n"); } return 0;}\nS 题3-19 for循环(计数器控制):求数列的一项/* Author: wudi Result: AC\tSubmission_id: 4104431 Created at: Thu Feb 10 2022 22:36:03 GMT+0800 (China Standard Time) Problem_id: 4574\tTime: 3\tMemory: 1664*/#include <stdio.h>typedef long long LL;const int N = 60;int main(){ long long a[N]; a[1] = 1; a[2] = 1; for(int i = 3; i <= 50; i ++) a[i] = 2 * a[i - 2] + a[i - 1]; int n; scanf("%d", &n); printf("%lld", a[n]); return 0;}\nT 题3-20 for循环:理财计划/* Author: wudi Result: AC\tSubmission_id: 4104447 Created at: Thu Feb 10 2022 23:09:20 GMT+0800 (China Standard Time) Problem_id: 4575\tTime: 2\tMemory: 1652*/#include <stdio.h>int main(){ int pay[12]; int bank = 0, me = 0; for ( int i = 0; i < 12 ; i ++ ) scanf("%d", &pay[i]); int month = 0; for (int i = 0; i < 12; i ++ ) { me = me + 300 - pay[i]; if (me < 0) { if(!month) month = i + 1; me = 0; } else { bank = bank + me / 100 * 100; me %= 100; } // printf("bank:%d me:%d\\n", bank, me); } if(month) printf("-%d\\n", month); else printf("%d\\n", 120 * bank / 100 + me); return 0;}\nU 题3-21 循环嵌套:寻找完数/* Author: wudi Result: AC\tSubmission_id: 4104468 Created at: Fri Feb 11 2022 00:02:44 GMT+0800 (China Standard Time) Problem_id: 4576\tTime: 3\tMemory: 1508*/#include <stdio.h>int main(){ for (int n = 2; n <= 1000; n ++ ) { int sum = 0, x = n; for (int i = 1; i < n; i ++) { if (n % i == 0) sum += i; } if (x == sum) printf("%d\\n", x); } return 0;}\nV 题3-22 循环嵌套:寻找质因数/* Author: wudi Result: AC\tSubmission_id: 4104470 Created at: Fri Feb 11 2022 00:07:56 GMT+0800 (China Standard Time) Problem_id: 4577\tTime: 13\tMemory: 1700*/#include <stdio.h>void divid(int x){ for (int i = 2; i <= x / i; i ++) { if(x % i == 0) { while (x % i == 0) x /= i, printf("%d ", i); } } if (x > 1) printf("%d ", x);}int main(){ int n; scanf("%d", &n); divid(n); return 0;}\nW 题3-23 循环嵌套:等式填空/* Author: wudi Result: AC\tSubmission_id: 4104637 Created at: Fri Feb 11 2022 22:38:45 GMT+0800 (China Standard Time) Problem_id: 4578\tTime: 1\tMemory: 1628*/#include <stdio.h>int main(){ int m; int a, b, c, d; scanf("%d", &m); while (m -- ) { scanf("%d%d%d%d", &a, &b, &c, &d); int exist = 0; int cnt = 0; for (int e = 0; e < 10; e ++) for (int f = 0; f < 10; f ++) for (int g = 0; g < 10; g ++) for (int h = 0; h < 10; h ++) { if ((100 * a * f + 10 * a * b + 10 * f * e + e * b - 1000 * g - 100 * c - 10 * d - h) == 0) { exist = 1; cnt ++; printf("case%d: %d%d*%d%d=%d%d%d%d\\n", cnt, a, e, f, b, g, c, d, h); } } if(!exist) printf("IMPOSSIBLE!\\n"); } return 0;}\nX 题3-24 循环嵌套:最短正整数序列/* Author: wudi Result: AC\tSubmission_id: 4104475 Created at: Fri Feb 11 2022 00:49:16 GMT+0800 (China Standard Time) Problem_id: 4579\tTime: 22\tMemory: 1704*/#include <stdio.h>int main(){ int n; scanf("%d", &n); int sum = 0, res = n, l = 1, r = n; for (int i = 1, j = 1; i < n; i ++) { sum += i; while(j < i && sum > n) { sum -= j; j ++; } if (sum == n) { int t = i - j + 1; if (res >= t) { res = t; l = j; r = i; } } } if (res == n) printf("-1\\n"); else { printf("%d = ", n); for (int i = l; i <= r; i ++ ) { if (i != r) printf("%d + ", i); else printf("%d", i); } } return 0;}\n专项练习3: 函数及其应用(❌)只做到H,后面还有几题\nA 题4-1 定义与调用函数:三角形的判断/* Author: wudi Result: AC\tSubmission_id: 4104681 Created at: Sat Feb 12 2022 00:15:02 GMT+0800 (China Standard Time) Problem_id: 4580\tTime: 4\tMemory: 1732*/#include <stdio.h>int main(){ int a, b, c; scanf("%d%d%d", &a, &b, &c); if ( a + b > c && a + c > b && b + c > a) { if (a == b && a == c && b == c) printf("equilateral triangle!\\n"); else if(a == b || a == c || b == c) printf("isosceles triangle!\\n"); else printf("regular triangle!\\n"); } else printf("not a triangle!\\n"); return 0;}\nB 题4-2 定义与调用函数:猜素数/* Author: wudi Result: AC\tSubmission_id: 4104684 Created at: Sat Feb 12 2022 00:22:15 GMT+0800 (China Standard Time) Problem_id: 4581\tTime: 8\tMemory: 1668*/#include<stdio.h>int is_prime(int n){ if (n < 2) return 0; for( int i = 2; i <= n / i; i ++ ) { if (n % i == 0) return 0; } return 1;}int main(){ int n; while(scanf("%d", &n) != EOF) { if(is_prime(n)) printf("yes\\n"); else printf("no\\n"); } return 0;}\nC 题4-3 定义与调用函数:cos(x)级数展开式/* Author: wudi Result: AC\tSubmission_id: 4104856 Created at: Sat Feb 12 2022 21:54:46 GMT+0800 (China Standard Time) Problem_id: 4582\tTime: 5\tMemory: 1716*/#include<stdio.h>int main(){ double x; int m; scanf("%lf", &x); scanf("%d", &m); double sign = 1.0, sum = 0.0, r = 0.0; int b = 1; for (int i = 0; i < m; i ++) { if (i == 0) r = 1.0; else r = -1.0 * r * x * x / ((2 * i) * (2 * i - 1)); sum += r; } printf("%.8lf\\n", sum); return 0;}\nD 题4-4 定义与调用函数:分数相加与化简/* Author: wudi Result: AC\tSubmission_id: 4104862 Created at: Sat Feb 12 2022 22:01:54 GMT+0800 (China Standard Time) Problem_id: 4583\tTime: 6\tMemory: 1652*/#include <stdio.h>int gcd(int a, int b){ return b? gcd(b, a % b):a;}int main(){ int t; scanf("%d", &t); while( t -- ) { int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); int e = a * d + b * c; int f = b * d; int r = gcd(e, f); e /= r; f /= r; printf("%d %d\\n", e, f); } return 0;}\nE 题4-5 定义与调用函数:星期几/* Author: wudi Result: AC\tSubmission_id: 4105549 Created at: Tue Feb 15 2022 23:20:01 GMT+0800 (China Standard Time) Problem_id: 4584\tTime: 8\tMemory: 1656*/#include <stdio.h>int Day(int yy, int mm, int dd){ int month[] = {31,28,31,30,31,30,31,31,30,31,30,31}; int n1 = yy / 4 - yy / 100 + yy / 400; int n2 = 1582 / 4 - 1582 / 100 + 1582 / 400; n1 -= n2; if (yy % 400 == 0 || yy % 100 != 0 && yy % 4 == 0) month[1] = 29, n1 --; for (int i = 1; i < mm; i ++ ) dd += month[i - 1]; return 365 * (yy - 1582) + n1 + dd;}int main(){ int n; scanf("%d", &n); int yy = n / 10000; int mm = n % 10000 / 100; int dd = n % 100; int days = Day(yy, mm, dd); int week = (days % 7 + 4) % 7; // printf("week:%d\\n", week); switch(week) { case 0: printf("Sun");break; case 1: printf("Mon");break; case 2: printf("Tue");break; case 3: printf("Wed");break; case 4: printf("Thu");break; case 5: printf("Fri");break; case 6: printf("Sat");break; default:break; } return 0;}\nF 题4-7 全局变量的使用:熊猫序列/* Author: wudi Result: AC\tSubmission_id: 4105578 Created at: Wed Feb 16 2022 09:46:21 GMT+0800 (China Standard Time) Problem_id: 4607\tTime: 12\tMemory: 1720*/#include<stdio.h>const int mod = 10000007;int a[101];int f(int n){ if(n < 5) return a[n]; for (int i = 5; i <=n; i ++ ) a[i] = a[i - 1] % mod + a[i - 4] % mod; return a[n] % mod;}int main(){ int n; scanf("%d", &n); for(int i = 1; i <= 4; i ++ ) a[i] = 1; int res = f(n); printf("%d\\n", res); return 0;}\nG 题4-10 标准库函数的应用:求面积/* Author: wudi Result: AC\tSubmission_id: 4104871 Created at: Sat Feb 12 2022 22:17:42 GMT+0800 (China Standard Time) Problem_id: 4610\tTime: 21\tMemory: 2620*/#include<stdio.h>#include <math.h>const double eps = 1e-4;int main(){ double n; scanf("%lf", &n); double x = 0.0; double s = 0.0; while (x <= n) { s += eps * fabs(sin(x * x)); x += eps; } printf("%.2lf\\n", s); return 0;}\nH 题4-11 递归函数:倒序输出/* Author: wudi Result: AC\tSubmission_id: 4104873 Created at: Sat Feb 12 2022 22:23:12 GMT+0800 (China Standard Time) Problem_id: 4611\tTime: 10\tMemory: 1720*/#include <stdio.h>const int N = 100010;int main(){ int a[N]; int x, i = 0; while (scanf("%d", &x) != EOF) a[i ++] = x; while (i > 0) printf("%d\\n", a[-- i]); return 0;}\n专项练习4: 数组与字符串及应用(❌)","categories":["算法与数据结构"],"tags":["oj4th"]},{"title":"acwing基础算法(3):搜索与图论","url":"/2022/02/22/algorithm/acwing/%E5%9F%BA%E7%A1%80%E8%AF%BE/L3-%E6%90%9C%E7%B4%A2%E4%B8%8E%E5%9B%BE%E8%AE%BA/","content":"DFS\nAcWing 842. 排列数字\n\n```cpp\ninclude using namespace std;\nconst int N = 100010;int n, path[N], st[N];\nvoid dfs(int u){\nif (u == n){\n for (int i = 0; i < n; i ++ ) printf(\"%d \", path[i]);\n puts(\"\");\n return;\n}\nfor (int i = 1; i <= n; i ++ ){\n if (!st[i]){\n path[u] = i;\n st[i] = true;\n dfs(u + 1);\n st[i] = false;\n }\n}\n}\nint main(){\nscanf(\"%d\", &n);\ndfs(0);\n\nreturn 0;\n}\n- AcWing 843. n-皇后问题#### 第一种搜索方式\ninclude using namespace std;const int N = 10;\n\n\nchar g[N][N];bool col[N], dg[N 2], udg[N 2];int n;\nvoid dfs(int u){\nif (u == n) {\n for (int i = 0; i < n; i ++ ) puts(g[i]);\n puts(\"\");\n return;\n}\nfor (int j = 0; j < n; j ++ ){\n if (!col[j] && !dg[u + j] && !udg[n + j - u]){\n g[u][j] = 'Q';\n col[j] = dg[u + j] = udg[n + j - u] = true;\n dfs(u + 1);\n g[u][j] = '.';\n col[j] = dg[u + j] = udg[n + j - u] = false;\n }\n}\n}\nint main(){ scanf(“%d”, &n); for (int i = 0; i < n; i ++ ) for (int j = 0; j < n; j ++ ) g[i][j] = ‘.’;\ndfs(0);\n\nreturn 0;\n}#### 第二种搜索方式```cpp#include <iostream>using namespace std;const int N = 10;char g[N][N];bool row[N], col[N], dg[N * 2], udg[N * 2];int n;void dfs(int x, int y, int s){ if (s > n) return; if (y == n) x++, y = 0; if (x == n) { if (s == n){ for (int i = 0; i < n; i ++ ) puts(g[i]); puts(\"\"); } return; } g[x][y] = '.'; dfs(x, y + 1, s); if (!row[x] && !col[y] && !dg[x + y] && ! udg[n - x + y]){ g[x][y] = 'Q'; row[x] = col[y] = dg[x + y] = udg[n - x + y] = true; dfs(x, y + 1, s + 1); row[x] = col[y] = dg[x + y] = udg[n - x + y] = false; g[x][y] = '.'; }}int main(){ scanf(\"%d\", &n); dfs(0, 0, 0); return 0;}\nBFS\nAcWing 844. 走迷宫\n\n#include <iostream>#include <cstring>#include <queue>using namespace std;const int N = 110;typedef pair<int, int> PII;int g[N][N], d[N][N];int n, m;int bfs(){ queue<PII> q; memset(d, -1, sizeof d); q.push({0 ,0}); d[0][0] = 0; int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; while (q.size()){ PII t = q.front(); q.pop(); for (int i = 0; i < 4; i++){ int x = t.first + dx[i], y = t.second + dy[i]; if (x >= 0 && x < n && y >= 0 && y < m && d[x][y] == -1 && g[x][y] == 0){ d[x][y] = d[t.first][t.second] + 1; q.push({x, y}); } } } return d[n - 1][m - 1];}int main(){ scanf(\"%d%d\", &n, &m); for (int i = 0; i < n; i ++ ) for (int j = 0; j < m; j ++) cin >> g[i][j]; cout << bfs() << endl; return 0;}\n\nAcWing 845. 八数码\n\n#include <iostream>#include <cstring>#include <queue>#include <unordered_map>using namespace std;const int N = 18;int bfs(string state){ queue<string> q; unordered_map<string, int> d; q.push(state); d[state] = 0; int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; string end = \"12345678x\"; while (q.size()){ auto t = q.front(); q.pop(); if ( t == end) return d[t]; int distance = d[t]; int k = t.find('x'); int x = k / 3, y = k % 3; for (int i = 0; i < 4; i ++){ int a = x + dx[i], b = y + dy[i]; if (a >= 0 && a < 3 && b >= 0 && b < 3){ swap(t[3 * a + b], t[k]); if (!d.count(t)){ d[t] = distance + 1; q.push(t); } swap(t[3 * a + b], t[k]); } } } return -1;}int main(){ char s[2]; string state; for (int i = 0; i < 9; i ++ ){ cin >> s; state += *s; } cout << bfs(state) << endl; return 0;}\n树与图的深度遍历\nAcWing 846. 树的重心\n\n#include <iostream>#include <cstring>using namespace std;const int N = 100010, M = 2 * N;int h[N], e[M], ne[M], idx, n, ans=N;bool st[N];void add(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx ++;}int dfs(int u){ st[u] = true; int size = 0, sum = 0; for (int i = h[u]; i != -1; i = ne[i]){ int j = e[i]; if(st[j]) continue; // 父节点遍历过,不再遍历 int s = dfs(j); size = max(size, s); sum += s; } size = max(size, n - sum - 1); ans = min(ans, size); // cout << \"u: \" << u << endl; return sum + 1;}int main(){ memset(h, -1, sizeof h); scanf(\"%d\", &n); for (int i = 0; i < n - 1; i ++ ){ int a, b; scanf(\"%d%d\", &a, &b); add(a, b); add(b, a); // 初始的结点不一定是根节点,不是双向的话无法遍历父节点 } dfs(1); cout << ans << endl; return 0;}\n树与图的宽度遍历\nAcWing 847. 图中点的层次\n\n#include <iostream>#include <cstring>#include <queue>using namespace std;const int N = 100010;int h[N], e[N], ne[N], idx, d[N], n, m;// bool st[N];void add(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx ++;}int bfs(){ queue<int> q; memset(d, -1, sizeof d); q.push(1); d[1] = 0; while(q.size()){ int t = q.front(); q.pop(); for (int i = h[t]; i != -1; i = ne[i]){ int j = e[i]; if (d[j] == -1){ d[j] = d[t] + 1; q.push(j); } } } return d[n];}int main(){ memset(h, -1, sizeof h); scanf(\"%d%d\", &n, &m); for (int i = 0; i < m; i ++ ){ int a, b; scanf(\"%d%d\", &a, &b); add(a, b); } cout << bfs() << endl; return 0;}\n拓扑排序\nAcWing 848. 有向图的拓扑序列\n\n#include <iostream>#include <cstring>using namespace std;const int N = 100010;int h[N], e[N], ne[N], idx, d[N], q[N];int n, m;void add(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;}bool topsort(){ int hh = 0, tt = -1; for (int i = 1; i <= n; i ++ ) if(!d[i]) q[++ tt] = i; while(hh <= tt){ int t = q[hh ++]; for (int i = h[t]; i != -1; i = ne[i]){ int j = e[i]; d[j] --; if (d[j] == 0){ q[ ++ tt] = j; } } } return tt == n - 1; }int main(){ memset(h, -1, sizeof h); scanf(\"%d%d\", &n, &m); for (int i = 0; i < m ; i ++ ){ int a, b; scanf(\"%d%d\", &a, &b); add(a, b); d[b] ++; } if (topsort()){ for (int i = 0; i < n; i ++ ) printf(\"%d \", q[i]); puts(\"\"); } else puts(\"-1\"); return 0;}\nDijkstra\nAcWing 849. Dijkstra求最短路 I \n\n#include <iostream>#include <cstring>using namespace std;const int N = 510;int n, m;int g[N][N], dist[N];bool st[N];int dijkstra(){ memset(dist, 0x3f, sizeof dist); dist[1] = 0; for (int i = 0; i < n; i ++ ){ int t = -1; for (int j = 1; j <= n; j ++ ) if (!st[j] && (t == -1 || dist[t] > dist[j])) t = j; for (int j = 1; j <= n; j ++ ){ dist[j] = min(dist[j], dist[t] + g[t][j]); } st[t] = true; } if (dist[n] == 0x3f3f3f3f) return -1; return dist[n];}int main(){ scanf(\"%d%d\", &n, &m); memset(g, 0x3f, sizeof g); while (m --){ int a, b, c; scanf(\"%d%d%d\", &a, &b, &c); // if (a == b) g[a][b] = 0; // else g[a][b] = min(g[a][b], c); g[a][b] = min(g[a][b], c); } cout << dijkstra() << endl; return 0;}\n\nAcWing 850. Dijkstra求最短路 II\n\n#include <iostream>#include <cstring>#include <queue>using namespace std;const int N = 1e6 + 10;typedef pair<int, int> PII;int n, m;int h[N], e[N], w[N], ne[N], idx;int dist[N];bool st[N];void add(int a, int b, int c){ e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;}int dijkstra(){ priority_queue<PII, vector<PII>, greater<PII>> heap; memset(dist, 0x3f, sizeof dist); dist[1] = 0; heap.push({0, 1}); // first: 距离, second: 编号 while (heap.size()){ auto t = heap.top(); heap.pop(); int distance = t.first, var = t.second; if (st[var]) continue; st[var] = true; for (int i = h[var]; i != -1; i = ne[i]){ int j = e[i]; if (dist[j] > dist[var] + w[i]){ dist[j] = dist[var] + w[i]; heap.push({dist[j], j}); } } } if (dist[n] == 0x3f3f3f3f) return -1; return dist[n];}int main(){ scanf(\"%d%d\", &n, &m); memset(h, -1, sizeof h); while (m -- ){ int a, b, c; scanf(\"%d%d%d\", &a, &b, &c); add(a, b, c); } cout << dijkstra() << endl; return 0;}\nBellman-ford\nAcWing 853. 有边数限制的最短路\n\n#include <iostream>#include <cstring>using namespace std;const int N = 510, M = 10010;struct Edge{ int a, b, c;} edge[M];int dist[N], backup[N];int n, m, k;void bellman_ford(){ memset(dist, 0x3f, sizeof dist); dist[1] = 0; for (int i = 0; i < k; i++ ) { memcpy(backup, dist, sizeof dist); for (int j = 0; j < m; j ++ ) { auto e = edge[j]; dist[e.b] = min(dist[e.b], backup[e.a] + e.c); } } }int main(){ scanf(\"%d%d%d\", &n, &m, &k); for (int i = 0; i < m; i ++ ){ int a, b, c; scanf(\"%d%d%d\", &a, &b, &c); edge[i] = {a, b, c}; } bellman_ford(); if (dist[n] > 0x3f3f3f3f / 2) puts(\"impossible\"); else cout << dist[n] << endl; return 0;}\nspfa\nAcWing 851. spfa求最短路\n\n#include <iostream>#include <cstring>#include <queue>using namespace std;const int N = 100010;int h[N], e[N], w[N], ne[N], idx;int q[N], dist[N];bool st[N];int n, m;void add(int a, int b, int c){ e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;}int spfa(){ memset(dist, 0x3f, sizeof dist); queue<int> q; q.push(1); dist[1] = 0; st[1] = true; while(q.size()){ int t = q.front(); q.pop(); st[t] = false; for (int i = h[t]; i != -1; i = ne[i]){ int j = e[i]; if (dist[j] > dist[t] + w[i]){ dist[j] = dist[t] + w[i]; if (!st[j]){ q.push(j); st[j] = true; } } } } return dist[n]; }int main(){ scanf(\"%d%d\", &n, &m); memset(h, -1, sizeof h); for (int i = 0; i < m; i ++ ){ int a, b, c; scanf(\"%d%d%d\", &a, &b, &c); add(a, b, c); } int t = spfa(); if ( t == 0x3f3f3f3f) puts(\"impossible\"); else printf(\"%d\\n\", t); return 0;}\n\nAcWing 852. spfa判断负环\n\n#include <iostream>#include <cstring>#include <queue>using namespace std;const int N = 2010, M = 10010;int h[N], e[M], w[M], ne[M], idx;int q[N], dist[N], cnt[N];bool st[N];int n, m;void add(int a, int b, int c){ e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;}bool spfa(){ queue<int> q; for (int i = 1; i <=n; i ++){ q.push(i); st[i] = true; } while(q.size()){ int t = q.front(); q.pop(); st[t] = false; for (int i = h[t]; i != -1; i = ne[i]){ int j = e[i]; if (dist[j] > dist[t] + w[i]){ dist[j] = dist[t] + w[i]; cnt[j] = cnt[t] + 1; if (cnt[j] >= n) return true; if (!st[j]){ q.push(j); st[j] = true; } } } } return false; }int main(){ scanf(\"%d%d\", &n, &m); memset(h, -1, sizeof h); for (int i = 0; i < m; i ++ ){ int a, b, c; scanf(\"%d%d%d\", &a, &b, &c); add(a, b, c); } if(spfa()) puts(\"Yes\"); else puts(\"No\"); return 0;}\nFloyd\nAcWing 854. Floyd求最短路\n\n#include <iostream>using namespace std;const int N = 210, INF = 1e9;int d[N][N];int n, m, Q;void floyd(){ for (int k = 1; k <= n; k ++ ) for (int i = 1; i <= n; i ++) for (int j = 1; j <= n; j ++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]); }int main(){ scanf(\"%d%d%d\", &n, &m, &Q); for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= n; j ++ ){ if (i == j) d[i][j] = 0; else d[i][j] = INF; } for (int i = 0; i < m; i ++ ) { int a, b, c; scanf(\"%d%d%d\", &a, &b, &c); d[a][b] = min(d[a][b], c); } floyd(); while (Q -- ){ int x, y; scanf(\"%d%d\", &x, &y); if(d[x][y] > INF / 2) puts(\"impossible\"); else printf(\"%d\\n\", d[x][y]); } return 0;}\nPrim\nAcWing 858. Prim算法求最小生成树\n\n#include <iostream>#include <cstring>using namespace std;const int N = 510, INF = 0x3f3f3f3f;int g[N][N], dist[N]; // dist表示点到集合的距离bool st[N];int n, m;int prim(){ memset(dist, 0x3f, sizeof dist); int res = 0; for (int i = 0; i < n; i ++ ) { int t = -1; for (int j = 1; j <= n; j ++ ) { if ( !st[j] && (t == -1 || dist[t] > dist[j])) t = j; } if (i && dist[t] == INF) return INF; if (i) res += dist[t]; st[t] = true; for (int j = 1; j <= n; j ++) dist[j] = min(dist[j], g[t][j]); } return res; }int main(){ scanf(\"%d%d\", &n, &m); memset(g, 0x3f, sizeof g); for (int i = 0; i < m ;i ++){ int a, b, c; scanf(\"%d%d%d\", &a, &b, &c); g[a][b] = g[b][a] = min(g[a][b], c); } int t = prim(); if (t == INF) puts(\"impossible\"); else printf(\"%d\", t); return 0;}\nKruskal\nAcWing 859. Kruskal算法求最小生成树\n\n#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 100010, M = 2 * 100010, INF = 0x3f3f3f3f;struct Edge{ int a, b, w; bool operator <(const Edge &W) const { return w < W.w; }}edges[M];int p[N];int n, m;int find(int x){ if (x != p[x]) p[x] = find(p[x]); return p[x];}int kruskal(){ sort(edges, edges + m); for (int i = 1; i <= n; i ++ ) p[i] = i; // for (int i = 0; i < m; i ++ ) cout << edges[i].a << ' ' << edges[i].b << ' ' << edges[i].w << endl; int res = 0, cnt = 0; for (int i = 0; i < m; i ++ ) { // cout << i << endl; int a = edges[i].a, b = edges[i].b, w = edges[i].w; a = find(a), b = find(b); if (a != b) { p[a] = b; res += w; cnt ++; } } if (cnt < n - 1) return INF; return res; }int main(){ scanf(\"%d%d\", &n, &m); for (int i = 0; i < m; i ++ ) { int a, b, w; scanf(\"%d%d%d\", &a, &b, &w); edges[i] = {a, b, w}; } int t = kruskal(); if (t == INF) puts(\"impossible\"); else printf(\"%d\", t); return 0;}\n染色法判定二分图\nAcWing 860. 染色法判定二分图\n\n#include <iostream>#include <cstring>using namespace std;const int N = 100010, M = 200010;int h[N], e[M], ne[M], idx;int color[N];int n, m;void add(int a, int b) // 添加一条边a->b{ e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;}bool dfs(int u, int c){ color[u] = c; for (int i = h[u]; i != -1; i = ne[i]){ int j = e[i]; if (!color[j]) { if(!dfs(j, 3 - c)) return false; } else if (color[j] == c) return false; } return true;}int main(){ scanf(\"%d%d\", &n, &m); memset(h, -1, sizeof h); while (m -- ) { int a, b; scanf(\"%d%d\", &a, &b); add(a, b), add(b, a); } bool flag = true; for (int i = 1; i <= n; i ++ ){ if (!color[i]) { if (!dfs(i, 1)) { flag = false; break; } } } if (flag) puts(\"Yes\"); else puts(\"No\"); return 0;}\n匈牙利算法\nAcWing 861. 二分图的最大匹配\n\n#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 100010, M = 2 * 100010, INF = 0x3f3f3f3f;struct Edge{ int a, b, w; bool operator <(const Edge &W) const { return w < W.w; }}edges[M];int p[N];int n, m;int find(int x){ if (x != p[x]) p[x] = find(p[x]); return p[x];}int kruskal(){ sort(edges, edges + m); for (int i = 1; i <= n; i ++ ) p[i] = i; // for (int i = 0; i < m; i ++ ) cout << edges[i].a << ' ' << edges[i].b << ' ' << edges[i].w << endl; int res = 0, cnt = 0; for (int i = 0; i < m; i ++ ) { // cout << i << endl; int a = edges[i].a, b = edges[i].b, w = edges[i].w; a = find(a), b = find(b); if (a != b) { p[a] = b; res += w; cnt ++; } } if (cnt < n - 1) return INF; return res; }int main(){ scanf(\"%d%d\", &n, &m); for (int i = 0; i < m; i ++ ) { int a, b, w; scanf(\"%d%d%d\", &a, &b, &w); edges[i] = {a, b, w}; } int t = kruskal(); if (t == INF) puts(\"impossible\"); else printf(\"%d\", t); return 0;}","categories":["算法与数据结构"],"tags":["acwing","算法模板题"]},{"title":"Linux基础","url":"/2022/02/21/ubuntu/Linux%E5%9F%BA%E7%A1%80/","content":"\n 98b9bce3395e8307c58744c12688842446589ee704ed9b7c8edc2bcde24642c99ea51d10e0d198f8b60fc94d68be045df9c1681d36be7fa79c8891e44879dd1fa35a0258f775c5b34c13a83a74b72e1e7d8a2c18d790df929db3f58d9690d72355ee5ece8bdb1d47e3bee09af9b7205991c3f9145ff492dfcac6d26459578f25f9bee584b0b2c18f0397f974427456b7f8567a759391abafa9a99fd41b4fcbd36171e2fa6aac813bfad1bfd6da4d32104306fad619add32ab2cffc74c3abcf02cdbf31156c1cbdf66f50770f01929564b05a4fc9ded939bd367b26e7c3c2d7095209d376f69f8cc6a61cc6a1b0f8883eeea3efdb60f5a111add42c662fbddf51df7d5b2f5c76f36057eee0f68e7f8bedc05adebf9c2e47e55a220112db3a182cab457f0568891a479d02934b97888bd8f028164192908a5125281805fa107e5fbd985dfb1082555558f079a1265ebfef6604090dd0ac6c053cd891a63524578cfd1e5377fc355d8c6ab39c74f845f838091875b3b92e3e8cdbb98eabc444a9221c70dce6b9ffe1119d9a3fc4b1214b7c9146a84f97c273ef87aa39c8941994048071c780829e202a57bdc71790c198d4a0419cd9c157d6bc340e05b110fb4d9f221e82b1bc1cbdea629f23f15e3f2a8c520bd883130469af2f7e26128f8d1f0e20ca953972df3bee68e38f6c178d4455f7e0eab82343a5ffb496c677af24fe290810962c54e8b0bdeeca3e5aba5943c7d28ad5348e1b34d6ce97010c9020505c6cf9474bcacb4d2547de38e15cacdc26f1d1475a69da6f417e103cc7c884ed43d755d244f2f55acea75d71ddc9c69fab92f24ff508cbcab7213170465090227500573110ad8bf795b6bbd1257255c09384e8a76e62de108b933b1bf922be257ce02f18895d43bdba725c3270af330ed55e4efd81f1c11e9fe35b3ac02f9b2a513dcf96af044496b8a9db36235da7f9a9ed47b570d8732bd1af47a12396fbafdd53f70d3673cc2bd61857c3bd19ea6b2e7ea8bbb008a5eed2d64672574d790aff21d8bf6f3d28be18d43dbac7e9e8c2d24af861e6d478bb55ac6bc7f6ab8abbfa1ada517394376d63d42285eb74468c2fb2eb05bd9d3c0bf53596a8023f46aa25812456460599123754738d6fd4bb4b3160eeb5bcf60b280fbea158d9975ec36d8e557b291f39e5de9edf55e401485f84ca44a02402f695293b8fa2f191d595651d5d46ea5691b8c7ac1d1fcac0d2125fb78c1664d8e815ab519c257b0589150b7c080f52a3d78b6ed141b31c13ea9def1b9225bbe49ad4a46de3a85d2ce2ab73b7cd265a198547e8deb008e4de2b50a2977b3dfd77b81f17a3f0a090b86c9bcc5df12daf8cf0b0eeb542cffa27563f62c28229b3bca9828c9f0b542ba42da10afeb23dd27972734de8ad5f28b3062b621c61815fdbf17d54b39877b3e70f1d703c702de37c73281b37064dfa52389aa15ad5ea58246f76d916ce30ef1768e8ce2fbef3355bee6e178654780d3f80c406f73da6931ad04488deddc6ce9335cad068bbcad709c5813ba0f4ca8e90b67a5b438f5b0eb655e4b50773ade3da5ee7f0575d8064b80011f0de3f274a4f57d0893b8e25f68b328915f597a4a65d21eb05770198ca5186cb73776ac1e6bd42192d28215da71a8debd65591b1874137b020f84c86155570490543093cc1d08b41bb4dd074b48ca468763d3d1b611383e6d5308c3a06e8fd4f65075249bd6b7cf229b7dbad432e1d7742791f0b58dde88ff21469d8c162c033acd90db6992c7933dd7d5f7a58c624a9a23b52f9927d1bbf8107ae8bab5e5883d31aa92ade4e1ebe696e8ed02fd15b5d258780ea05c638827e4a0c3049c86909cec02b67afe1b318614b69a0e7ddf7b2937812c7720ef93c2ee5f3a6ebfc22c6e83dc71ea4148b79e426c284240306610b3e13021382ef249eaf5c86f0204673a9549df20b207e7ed054a62cf8238e7c7b99345d6daa61c646052ddba4d9f9cf0429fdd73fbc9525adf15051eba2f211fbd6e5dcb13a4b1bcf5db0b5ccb46dd6621330c5aa9fa5eaae9b2ae424a7832b742eceaa4d8b3afe60e371e90e30f48c0c62da3a1f97ae35a9925f6c76368d5eedb49fa548cb9026c5c42d6df6726ef2684837f2e1678e072b92ce45627eaab23be9f0a39e9f9252c50c3d9d2629a7ae7092345b40e27f4e06b1de661c8ea5cbf2e96290e4d81efc292a3350543a02ed9fa28f4f6816959c201ee4e798ffaa845c6c1bfefb331f5b8a68f871bea240097d07f03c9842f0d5af9dec8ab6988f0407bd5c50a4377c2a81708d1042a923091b7f931a5f2d7774eb5b0b5ff8e58e0976ddf29b73570c5c0dc18845a6d5353f33a21ec011f5c5f47d69f4ef42910b26e688f4f8c318d2efa33737fe0c19cbba1619d262a933921f9863c0df10eee62ce893c6af8cc0311e2fead7d249395b4a85fe8d6be80fc1699773f2dde74bebe503587d77c9b4353c8188bf3f6bbc578f4bda24260733c26d078278e493289406328b18c4bd86b8b0e65a5ba1678eb6d403eeb9f278becf2a6fcde4a2d4b48d57436ff5235853e9653d0680e04f4572e632647d7e44ece6b4154f9e69b9d23033f83463dd0b8385f72a0be0583ca59f3c0121761cd4bcd8220ad95db7a826393ee38c17cf0448e71c0e9520305481750becf057a343ab917789fa6ebdbf5c7ae176651b92ea51f97a2e61d969ae025ce1fa59bac52675c912f3e484e168e71bb7d82ab42c1f0e80d3312470d5e2a72c5d6e67ab1fdbbfbc7530e3c322d352bdbe8c987c3a6721cfbccb433dc3147db6a91abea6db24404d44fc4a7f569ddeba8d14602549c5f631331f4f93ba4f19e81054450ca2c3c85a5fe17dee8718ba985e7263f7d98c351b8b250731ba03239850791bf6ed096a30987b52ed53637cd53ea8f9fc25766cbf998e7905dd17dcab58f999973ba34607e2a7138c1e3e8a3f9b138385a6dcf0deca6c2cf31dc4fc239025d63d87875a6395847dbb42ce83e416e5307a60a77ec63340fcf4b7a326c669be92d7c69c406c97da6d5a4034c073e3f93b42538174e7e83a9986ffb4c3bcb1eb8377ad060cb2f1610a25a32b00fe010cc1002656d6392807ecddb9553ea3875717f566adb08167d38d6f955f7f272c4f08fd3e0c539d76d53f73d70d65b5e00d0627a5db534a73e2911308074ad913b2f2fc9c32af59dea06bb907d1405a3d4c0f85b1dc0e687ec686710f538e7ded0504d6b5e3c0adb47a061594f642cc604b72b03870dfa1422250a635d506e53f2b1ba43fa44d9ce202eeb6e779a249306f27ab67a3e0333b46cfe9093576c73ba74f4b700ad3bbb53bef93572272301b1c6b410ea322d8979fe6302d7b542691abd145bc0cc0d86bc142090de9a80a61743073cbde7b9271bba5dd7c041b88202541bc8b9d6d755455e17c9cca019562f2b813f993b64735d0ff7fe2c6113d45a655d10d624208272fb4dde751ab5f590b23d259084ae29a01236883588a2163013d93d3c2f29b9c8e4f01b21f3c9ab0fa5ee8ae7f5d95135f750d4d2b2b5a8e25781fbacc5e5e58032a1833b840d0c190480aaee7ebfaf8bb47f465147d93ef9a98e85913a3a0022ac3519c104bfe096471df09cafaa28ba4141f22f1706d684621f0aa89227d8af139db487439976d5debd3525d791d82962d58264da51b8ca2081dd49ed71211b1925d656d53c30531188618d8e00bfbc6ffd835832027db40d9da221c1e76ec192d22bdc518c2c6e8a684ade52abda97da8b4b19b6c031b5561cf824f52c7ba12bebde0cc28949c6e40dd5b0da0257f75706f547eba036bc10769cbc0692cb8574331a3a75fec90792ae4527ac96b336d529323be0ec36b1c51b54bec8a935bfbb923892aba43c642a6a1dbd22ac0ab33c254d4e7f918ac9f3b25111a99925ada277bb76156a4a17ea8bafdb94b6a83a16100c84237bcab48480a20596fc1a8b24f10d0c1f793213ddb6cf4282ef76cabb8aabeccd689bf50696be07d29c71cd22b70dc8c32891c0057e89b5b8c6bb2c7f5f78e6ff9eeef6f4e3da31dbcd880ed53387475a31852ff27d8f36d97720ef211b44c7bbdfeedd5d8197c748e55db5eb99bec1d71b65d2af69905050943be819d539beec05d98ec63c4173ccdf25a41b2f2bc01dab7ea2f5535259e10cd81d7c0dad9d2910ae3ac39cc01d986c2ea28fad39e5e4d38349c02cf722c072c973d8635478b498d5fcef1b44e0095ee823abb58c23d93c83afad8f0bd2953a5b45c31492defd2c19eef543f1b404b53fa8de3baa233b3390427ad0c9b6b83aa77311f42e87e38063563862a8d40e0bc6105db118cba0fca9ebcc8abe7f1fd00d4df5a14f9a413f99365392e4f3d8b566d94eba6ee00397c2d05dd33e839aac362e679080ede90efe0a6e6cb35dc15c34160d41fc280d67594804a91ac59bebfc67bc202673aeedebc30fd1ab2baa31ce3d77744ce3a45950c59bf7f98d03ba88f7b0891b06fe1768e964a52d3a0eb99782a70518a5ebce567e6c96f65a2e12a5d1fd665dd48b2756dc433db5f089b9d71cd33a5b9a35bd13fb1b2cf15e3997ca33ba5f08b917afad8f9d6cc00b600fb1fcc10cc0c013bc079ba32ede84ed3fb1954f89f875c7f2baa7050416aae8664ff90d1b4003b5ab67d4de7629ad36f660f79d54f87b465368e847d3feca9422fe61c28b3a2c5ef94a46e232eed8396d328a18c32925a11b41360a0cabb28d62699bf083f24d952aba4b1e25aa331fd8804a99366af562779a7f11d3d3bba17bfc4769dd26706d2d3431b1e75e4f5698c6f2ff1ce76eed39fe87604168b508fa78eae90d4b14cf354109e0c88a0af5cd9300d6202f2c3634abb3454392cfed1a28071f4edea1a1fc2f92c2f1b8e34dd4098c746d957aa26865c131b61814de0a1977eac1a2240e6ba66267305c56c4e35be6de8914cc753f8752be24b5d75ef172e194a584c699d3ea45ca7cbb915f982c5fa5ffe4e57bdff47d120d24b50687b353164e32e998d89b7585d457543019771465ee1f01a8df372ccff3d9dbcad7d6366376058df847b8f0b3e058d3e0726ec183977e5da6d96e4df1825dcc4a21cdbd186abe7b7e3929be538f053d53a4166020ac332d1cbeb9fdaacc52521517715a665cd712bbdb8ca446a4c543b7fb031f0d2a30bc16230840ce210464809ee41a24eaaf603bbe459940ed95cd532eb0fc4545e60602c8a852cadf8c00fa1162527fe7d4e04c3b2cec35abb813e5b5b7482e37d1afd8d578ccc4db141d32953f6fcf48b787d343f3d82fc79f19537f2780422154de4558ffce7389f161afb47d6e3a057a10d763fb44752e7126ab29709bbca7cfcd1df639be5c49a3f4729ef216777eae2a2c130b38b49e5b374eef30d204a5f63ab203e25eadb54e8d53ddb06ba9d1f49714a41d8a678c5e23e3fc978c3ce5c6bdcc800cdbd544ba64fc67bff3b2ebc2d8c7e9e32b559a414f823aad1295ab0bce9a9632f61d1bbee046005ee18bd587eaf335189f9400601817272990ca3834bc6b7c1ffd00fbc2b0cd0d00a0a0289c026ff91d77403a1f242e4e6c0fd754d2aa4e90333ef8aea4e09e2d952ca3e88417a3f79d69f3d2798ff82ea28e521169d15b83605c7d0bbe8b09eed593e5ae07e32518ec5bc0f7f1249b681205f580aad5fc0e1103cb24f72fd3b4233eee5ea9631682bad199b60ecca1ad7a961448c81fe29d753896fc909dd70b2b7ed4ef3ceab0638ccd13f972b0a2a589577ebc8e68205f4be781f7b0e45c8284c4189ecd1572476de3e1459bfac06dc0abdb564139792ed4d9758d972ae0617763eab0c31b2bf9fa2b8d9b93f98eb3d08a51427c1f9d15475c1c3c1beb951e71a019351911c80fc1dff5f67c632bdbc11a59dbb6fb56785c99cbc737056b1736cdc4a8ab9083aeeb40062d1bc310003829410072f4a023a2bffcabe0f51f9f543237093630ab31efb4a1966bbe0de5e46c5b890b99bf737d8d013470ca594e34a1f149884bea9c6afca5e2257aedbf623b9dd2420f0a72961a95e257fe5e05c664c74ad40e7cdd3e13fef14299a36b819d044b3d4a48e2a89cde38cb7a5d11db8518b8db584ea364eca2f5e05b08808ed616fe219b54bbf9bd4dcec575b858a06075026c93b03e5c4123dd228c3019f62ad7690b5b4983f5f5ca3eb4b595b8b4d9ffa530147020aea1ab720962f557403b088ae117394fd6beae9f9cba2f7ec912003a70129651862b48dcce704f1fd8f8634f0126e1777f57b3ea8900d8f098f2dd9b5cc0fd70156417449fc2ffbdd2727654d8aa4af042a1d99613a6fa4c69b6080496019a537e9dd4074a54a964a4dfa159e1bc19c007482ea66f8ca36279beacb0c0f338f28f11f17b1a44bb8f50ff051717d0db2c58dd619474a876e68f55397486a6edee650b86cb627d99b84d4f4bb59d1e5e1d94e6b587a8bf71c3a0cf486ecb357d8618482650a5375ed6da11f21efab5955c67099ccd59c1983b698679cf2d9059c2d35199c77dec3f00c178a7c1ef2be4295dbb336fe1bdc00a1c1600a0b7cf703ffdbb2963d56b5e10ea83286094af4cfd25f2dba83c777e1de36786689b29b95cb7ac42c611bad8f81244978a9e27d34e1c4fd43258baff2a1034a1e576602c717e135795f014e17d291f17c8880c8886d63312a838fd86a21e2b93f368e70a66fa447c9370c47a9b126f815ef53e953a225e67e121e840c161cd60f0b008e6220744e9e451611e7927e44467b923b7f8aa097d97cd4e4633518abd9dc551648a05dac378f3eeda81b346cb36b96edde0faee709c85577c7848d226a3a34754e13964bc66b5824ba648fddb0e16bff533d915a52ff50b035673020e8f7adbc079a0d79c60d1cf6056032e252e0db13b98a05f59211721c03bcf6fb3e7b025070d82d93e0d83f77b04c941bc33cd96b979ec10baa88cfef7ab059fc5e54643d294173446a8e123537ecadb7548dc5a401cd5c63545a1bea8a3f02e74f03bde675c744d5d1b1e17ee4de20f01e49a5b3cdf8e2fc8741ed8b41f186e05f2d96ab0a1703787840a7f035ee9a55c02cb879b333397201ad29ac84811a7f684ea03ada8c26b7155429053d8f3a640cf630d7dad2059226430b7cdc27d242c931087f9886f6eb918431cae1af3362006bd1f202f6d4a40dd286d2ad5fe6d630e9bd21c92f42d1a7075ffd0796afd0b3486f0a4f957828f49981da901187cb917733e8a278498cab5c0485114cc1539242bc655fdaf5979c2bb113014efb7b8faeb6a77ecbc899b6c49f18d7481e45c16233f5f0ebd7510da4a1e5f37a426001609ed2fbe800859ee38323b8afff47d70b617c835d77572974b700174b2e9b804ce65ed50ad3ae65d70da4c7ec5cb1d260b5dca7b068ac2729a6d74cd2b4b70e75c950f0d7e9015904472f59f36fdefaed006db1aae8a3218727b65595cd217d8582d0b010e2d3a76207cc989e3dd54e4b589f624598963e079f8f0dd21977a4ef91e5bd41036d2b2951baf565b98a3c4388fcc3b4f77b43475d815b3b89b3f7c9b3e05fb192ee566cad4abcbc9ab84ade60fe99bae1f05d210403dc20c95f8e42f84cc6361e28c8e8aabb39fc45e9a5f298c49b9eced9249fc5935598d132cc427950c97bcf1a8c101c84fda534296136c32fc00200f99f3a18aa267bb0f694a3f5a412956ed5b752fe6a8ee89a56f5b9271e6647e3e8ac79cab0d81e0e9d138899c72405645371c886aab30f30fb73b534388e4a058ab86aa14bed5dc9e6b614e8fcf75108c426e65e8824347f4fbabb220e8ab945e3f5fdfefb50c7c5dca75fda27e0a90915053eb0a1b5bd7ce2443b496f5c306bed806614010d2b0dbc1caac2d193e8930504aae9bbf96196916638f77a02d0758d5aa9bc4ea53a288786afaad76d565d89693cc1de1fa0ad3e89f0087547881dea0343f2ce38f0d4c6dc525baaab78467307ad7074e4313ef86833e1eb77a8a5b4c93b4e722400ccef772585e4cb7002c6af8c0bcd56790cf4b71bb6552353c0644ea376669b9696cd306f3d324ff92dbf0dd093a0e1d358ddbf36d024da0aa12236c01e401f425fb7bb24e3a7027935991c834dd1e76ef41ee29515b3ed5f674bc57ce2d6cdef95d096aab92d3d5b29c5849765c31401879f94e88773dd48067f54f004983062b41543720b8384adc637043dd8d6c47da947d2f0709322942bd1e1dbb761ac50dc3d080a3e469654ffcf8f2dda31141135c2642d21c9c8cc6fa0d3b31e66091119ba1c8cb3891914cf0841a1e55619751e5267d03f137fa82d592ae44d62c478250dee28b4152933c7fcb2c13ebed0795bfcf186e1c1b10ef2922a48adcbb8570bbf108566d355f7187a04ae0cf66a8831b10c0f9f9343ea5f32981fcab9c2d6ad77eed70bcb4e63b926d5d1801c03c75d993fa5822ffe739c992c16b80fae7d9a1d74808f2ce1b31388f56082d8dc8923cba573cda37b29f2340dc15a0bd57e183016b05d940b130719a00235abc9663b3b6cdd55cd4fd864342f70ae17ac4b3a11191eca4e02a8f8cd213746c46677461592ce3d5fc9fe2ef1b5a850b61742c942adce6bbac06fc70b59f3de23ee37fa1a233d672120b5735e9ba512cb98774422a879fe882e61ba32f55ac2cd225637a0c174ea3e942964157fd525f856a0347f3d283d61cd7106090e90ad77994e15dfe6a4d65b269e15c5fa7a252cd54b91b769c7b0f1b0c0f92cacd8875b20751e774cbaa9bf09de38f6ad1275da1572e655af4d9f387284120ef9d70dcc3a95da4d724bf4a984f5eb0a913a8eb5e9f208fd3f354922d2c1fd84114ea00b0586b16fca8540ca44e9c52626f0fa0a47de154c1cfe2332132d9b17058aab7bd3ccbf45f76857e9838666a1df77b5dc48848e5293874caa28bbff2cb594ecc63ce7835f117c4cf59617596049f341b5d1682294205239daec60cc9fec998dc77eb2f43677aab501768a5badc48701b0a5059eb6d5e6b37a74f274d65477d7d0836c9e9e811ba4fbd05fc55fe8782ffa1fec931f9658c2e20e425f301cce19cba43434df6c841a73ed4fd7facb4072bd461aa0a05e1c90e174e19c471498425cad520dc23811fbc6020844f5f3798bd77d7cbb5f90d41180a205b7c8aa56e77e3aa9e65c54f3ed6f63f75b45cbe19e0d63ca5692f8020bd99fe6257eaa1bcfb3533a629b6f24cc6892769ea309b2cd80b2a0c6b110e3b6b20d3c21594d6c6abae442ebb5d091a4eba872c55a398c3f5dd21fdec1a529625376e1d9000834e89caa1f922855844a9e0e256aa0200a7b2a71b4ff12cc4a2e62bdc3d2bae1e15d306d1ed246e159debc090a85369a5f6163b8848e076b91c21ee2becce2c4887e2feecaa6cd25adecf0a4fe13b2afb8f5454005cc00e3a7e042a250fd25174908a2c41aa26a24acb757d426f6c75b95c8624a59e984ab7a1cfa0032d559658bc01a1b45b66779da576bc404092ed3a60a46f4d51168c8e0cd9ac4a35be457cc813ec400ba2d14470a8af3f0443548a92b06fe725848a72e8f593c583a27e8cf0f038d02da9fabe7c2829af8703e036129fdf071ea48e039dc1b634a02581a9d6b229ce947c95da732fef0a45fe331a3dfb2a40376c82c16c45fe770495bd0f917891db2b923ad3b500dcaf2496ebb72d4c69487a6119d97b3b939ba2800b3b37885bdcc0e27ae36f222f4907aa5aaf8df804b274535a6320e46f6a6ec670eafcb97e821dcc8be08d66ea6fcbd79d5d6c8d7de21413e1b28b74fe399bdfb91d7619577d1189e3fa558daaf7ed6732b93df5d21bc41bb033494a678dcf1ab8bdd8f612bd088c2c8e65c7a6dceb6d779f65938e49e2d080935545e62460100e6038be4c76fb343a8a9182bf84cb9184c9ceacbb4c11939a0567c24d4c174e9530e53f40894bffd0ff592ec29d86173f33eefe8b543778d93e002cccb3cef1e20a17f0861e6853dbee5b7d21693e3fe03f79435f98dc22daec7f7b9c529727e6740c9197d21fed95045d7900ebb4c674bd60efc333bda6171aab795b4655467abc62cc610ab58595f27a7b87893857083e7d394192f81a2c5e2f8507e897dca5f2a3f5ed94fe3d243c13bc6a87400d3449b2d89ce3e47493167b4c7ade5b633141cdbc63fc7217a37bab46520a4a4a7b6c0989e3b189d2b3991f1bb7cbfde364e8f170c81fc1d39ac12237b3cd938041fb1f945adff65e06faf46deeb8f9a7e69990681dc1e890c5fb69d9290ef4323ee295f0f19008b04c6011adee4d9069b227c2fff2a6a0c79d7664014bf1600064dda3c896e60112845b0cd8119ef89e453a77eebddb40dfb093227a4e8bfc525f795b18b17bee625aee95d4811b9eef922950911e40d4aaea024209fbe73cc5807bd5a380309c0b2769360b91b478f2205cd478071b3b8f1350999afe809fcc7abf42292153bf823f5789754a8cd6fa0f4dc63e8e2ca1af2213b34c4c623c3517ae8ad127e02026e2218a922df8e71fd86b96877c4fdd5c970481502a15820821db4752dbe76ecccf13af255cbe7c20cee72d1a082c69c6502b4230b5f33054d57cbb0712bc1fb71fd11d6f8d982e9898457db3c0a1b111ffa1763c5cca8810317003c07f900627c13c529a4a2d1d2464126ebf4b493eb838de9be5f53334959a77827c6d2d26224a13f9bafeec08526d41fc150e70842e5856bc2855d98fd5b81d456a1d01584db3fa3fc687879e30e93a6310d7bbf056746e08315cb7104965ef67661b012afda7d91554b62cc5bd434e10f6808084f32a0444fae2719f17e70ea38141bc5b52506d9d83fe35db28b9391e311ed2c6e79ff46ad9e658247efc319cdae7de455db8d3996d6c9b4725163f326686543abd1773ccda46a3bfe0730765dec241a7e72b7a94b4e0d67bbe1acc3d9651998ef3598e66097f3afa3c75eec273e64574e1f56424edb45824cbd236d77d5fdc2e6cc173f283bb4034551e662deeea1f11e16a7a247a1da442db54fb8aefc86db3c3c5529fe4a1d584f53494e653240eddeb2494ec24e377fd7b5c74d9458fa158b37e820a592adffa18b8c5839c2739b4b32e17dcf7e084892c002ef7a6df588520c575a1b6108d1ae46a5578492c6cad911c4cc896bb8e8bc2ef6a4ae534cb28ad11a0f53358d5da6fe4f9f87532e971b3d019feae8f765fb4837a40f7857472dd789eb26c0220d0bb9f339e53273f052d806aa791d72f165c3cb8cac3890f68af5688055bf853df1d756a0d7633be695b9b92ce3d55abcac689b72cad6c0b134b0b0ba87e04bfb9c77e35c30e7d32f5d0ed949b8e223515c5dc23ff85c12d484f6f88ded7c5dc1615f4751f3cfddd3a9ee1a4092c07412c6fe73578ddf924dfe8364d85b6c9921d82302c43f610a5cbbb3aa2b578ae0aca96816f461263981c74d56c1323566274287e627e7b9c229b57ea91ae1b71e9e1f7452e1e9cb414691c06a3cdbfb7571cfe7ce7ab8f9d22206fd6037e11d7c3d6e6dee9a5b29987707b3ada16cba28b18c06b58e61d05d589e53043042ff870e5abb3a4f4ebf19897415ef4b9623fd5774148d244151e12fbd48e94bf604fde3ab24f368cdcacb6a2e106f5b86b58b16ffe87ace2952c74b950982d0f49fb063d5cc52fb5203682bc7583e2efe9e6c44a3f0e9f73692c0d4fe9b8a711363a4d0088c6ec97c47bd942eb7d4c751f7892ef441af014807c72091a1883772be8e31374975bb078eb4d527fa716f86ca0e25ba9484a9ec0e258de7f54c8c7592273d103319e3ed27fd8c80dfeda511ec4f92cb250222494a5f65c34ab3578f0d12dbc6af3409f2068c172540ad5324a94698a48a09d60c376d1704edb1979b75ea43d52a6417443edffcd0ac4047bc87db43e9d2d70e08e84444e3485b9c5d6e684206303fbdf9e9b11cc8016d00e48a3deeafe84a6af6d30490100ad7ad2e15ae7de3a415008ecce4bf425deebbe51409c9e8c7ec683120d8926058491d89dfdbc5c21cf3cfc0cc8a9f405d904373f15a550ad0953012b24be0bfe9e6ebcf6a6fe3df0b5d33a371ad104c1424190400b73ec9d86f91304eb01dbaf18963746fdfa539da99ce76482471efafa8249761b9cf16f103dd549842fdad0f893d238ce5350503fafb025c57288ee3884e61abf1b57ddf4b2a4dd3fe34a3c95af7d4b8c74779b3677a07e9c80392f5a8108886649497f6e8d77c8641db20a026ead28648d52d240da62512ee6826836bb20f28b655b06d0a7ab1367fbcd0e35c3624d281f17b9c53e4601eee4f23eb3b546fa8fe2ae7b9f020dfd953cd40ef40a15854fc388c937e645e7e291a60cb79b9f6e101785713eabb682c4b1d5b3fbf9d4ee7d54399221965662c51ef43cd14615b83d151f32e179a0cf4360d593d9d75fa2848daecd20ad7bc8b40da0dd71a54a3ead2f04d0516735872880fea64c993dd6bfd887c6bdb37b45521e07c09877cc50dbe075e154d7234d0bad1045619d4765f1ade0cfdab93eccfe9987eef231ba686f947debef223b9ff5c9cc9dbd4308fd7eecf1a27407f4143b0b90cefaa6028a2dae053f74a12ca230c2c2e25f868ae2254bc449a61a5ecb0bf12b9228f75f8a01415a3e2cda8a6674eff2b5cc7ad6c58ad3315c9d3556233a50ece973bea43dd64f33d3b217d73a4f76fcb1dd9350ed55043082e4c508f01f59d75ff9a181779a5f72ac41350b72df867fa6efd034cfefbde3bb176d9fd1d0fa7da48886c9d7a87e8335318eda51f6779dba9b579446c778a884bb6bb7b9245539e9252e9b30b9c489b47dc52c1ec121f18cb94ecb648e48a655335876068bb66ace790879ad70df9acaf419a85d7f038430c5afe4265ff0258d9a9c9b8a41b2101394a0d9a14fcf61c2227be32e06cf53f01767b1a5c6cb7fa44ddf63c170f92bdcf8efc087b0238d7c12a24c9b18c94aac99a5394780d6e75a550a347cb566bead14b5667ea6774ef8102e79032096c0ca0398bd780f592889a746eabd457e8c25cd5a8876340a90d1bcbc05ea13009f28d7aee233235d581151d1d591ed8af42c766c29ec704295d2dcb331df36a341c3db5ee4360edc405f7ae33072cb1aefc93ad81277a6bdd85d5941df0f65ffc57bf4200027d2b1ccc239d9afb52aa883d8f4453381c42ffb28c8743c51e3cdabb5cbf83218407c9a3b3260930bad0bfb077f5c54b5d0c0c0b4bdb68aa40dd7784eeeb93a95c3ed4813b74e3b563dd29c1e3d731a42259b5610ca7ceaaa030388ee64f03e21a4f961f4f7e4508a733ff0b1fea93f2aa17580adf7e4f4917ceed97946d4f98f565b780365d948a99c538b51fdb6ce56c45a9eeebf9b620caae62819579445990b59e104a4dc984e2257863baf74ff727e5f91c6bec36fda32998f9a68856439bddbbb4709280e42ab2433b6916db67556cc4a53f8295ae5759356285556869e97b3e0356234f3c9ea195e0992d06f828fba4deb126d1679be8d8224591fff1981db809f69eba98f4471decfbfe7026ec78587c69abef0fdbbf1b962f123e199629d9da8ff5dae35b79d0afc826d79174d2beaa7961139b4b32310c2496b13e7c766088102de8a1bea184b552a719699c4fe392416a28e79ba8540cd35f47013bc9211ebdfdb7d0f03c59f2534b9a45da91475c887e1ffa5cad939b98cf6417145c4456dd7f5a3d525e699191bbb763edfb7e84d7dd7a158db24caca8990537b5a4777acc55c047e808e69bb095b073bc8fc77d3b8d67c1e6691ffa4cc89e35675b2d65560de1c994fdff6e472dbbddce72f38d269f97908fb8ed62067a89efb69eb6e1bf2a7949b96a5072e473409aa29297024173253907a00d2a9b2d81f70f54714ed6d9a2c113884940e57bc22a84022b9169beb046f71cca57c3c746c7facfe48efbe4e6802a194ad39789595007440c18625630a4866bb43d3178408ffdd8fadd7c1564c1b8e96ed82fc93d289fc94a3007068f282e55e640de9ab35b02038f5bd47bb4449ad07aec9ba08be3bdf5617812883bfc62a238df691640441654db8d8e1ea1966b8bdec174da2776fd57c6fa35f284b232019f871cc95b988a744f7e3781e3882a45932d9fd7d156777c05bb7cd4d63eb07fb1551e15e9df17feb0bea06e434ffe93eee6565f1c4c4b28d03a3084950dd23a89967234df95d966777df6ca2d1f2faea342aaba8d513eaa6fdc8623654a8a1cd836afeb59ba11d65681a8e9a6900e94f07c0deddbfc38c02fc4454d67bab5b207f91df043712fc1e77938b646943d55143c34eb20b8520c476b203370d20a5f0099a7a1b9d00ad71b90d2d650300b1595ea5f1541093948a7dad72b7fa94bf2bdfac45a17a8376334c5b31bedb0964660f803e441e64533baeca0da0b325f8da531953052cee10cf4fda721a71c4199005b408cb9086abff7bbdd49f649e5b611daaba048685e332b8b8f708f155a0ae512eeceae0590f1a53dae963fc9ff7cc09e963885a37d0af719c59bd123507b80ad99c36ce86fa3662d8349bf1fbf19206c30ddb16874fe6746612bf4b0c2a04957a551bdb2d1a75ae9e234a309c5a3172ea11e054112a55cd60956dfe25a560f2c3a37b0a6c6b16ed2ef7f41106872761d43c7629318bd49b09bedf88143f98cf12086933a3ee4df14edc54b5d1b18571db0bc94cea00505bae7b749f2598d9a45031869e0f81337830dfdc1c25143fc70913056225a4abd431d7b45f3003d58fc5c78232102edc6caa294e1040bc494c6c591f7e619978fe229e0d399d99bd1ac73bec6b51e39b43561322e0bf5e1dd3bd60110572abdc135e1966332d6b6e4e3305e35425f64ef7c9cdf3f1ff039075b7e361442671097653f2451a4d7d487fa6a9c3ef8da2fed0538a87868df919ea5e074aada1a90d633c74147bfa34cb18076210dd49156f82141c57ac039d1ed1b1a13933a057ca4ee13ec540de1d4993abe78e4650223f3f6f12b366476c5fa8b3d5e5932703ba5c4d35e526842b4f764757b3d8db0b29349ddc1684c3f0a8e804c5e746184927f27401c6ac9893e0fb1e9a9ef857d4b537bb8e024fa212f93907eecb025f462793336b9d86abbfb535157443404b47ee6e2aeea5df8be168a03dd92a34e98f058b9a6a406cbc35c665a4b75c487cfa478beae9860914f341587dc58f2da6f02beceaf1765ebdc3d4066006f058d9dd595b4b09cc41f73377c3590adb3c29a165ed0eb1d8bb1f10af412edb9cf163f0ae8962c02449287eece16ec59d638c5553c62be7a2a1a56d61a6954e4cfac69666f77080f7310bef8ae3d6061eeceea005de992aaaf9d83dc7d17e1bb2b1fb3eb938634b89d840aa7d250af59f5b7ea80e6c2abedbc536980a4ed7b61aa541f20f3d7c93268d21b0b111a4a16870b7d128c6194b3f93db05e1ef379bd1ffcf248deaf104fc1f6fd45146703b8769c4c34fee801de594aa72d0636a49f3d38e29b6cc5cb1bd56c7b5034723eaba0ddec9f114fbc81f39d4410fa221ae876ceb054e8db391fd3355e44842f8937ab96db11fcb1e75224bcd45aebc0f03ecfc7d8af966570eb508af1b513b4d417e9571411745b789b44438df6adf035782d127615c82b40108c66f3241ee8d93ae3a39663e50fe5c9eeee45a6378369e54f021e84993b2d42849ffb87059bf49a10fa519bee2151f048df16dcee55299f3dda92af848bd4bd8687b4af309aad24674b912222759c24aee2ac6e5c1ee4993ec53844af697793e1d3a2f087b0cc8bd647048b02c82a51701b89dd5c840c3554099760079f3345b6340f0aca7aab2058494ae3aede7dfafe495103069f533ed7bb1497216cd9570559915d05c0630158d452fb61b8b2da83d14b894bafda5240bd2a554cf25daed6a2a594138a20365c4ddaecfad068391b3837f96aaa5789879154fc66c296297b3d941253eb803410c39b09c42dc62ca018f91f444e7f311e5cbccc73a0c97d863a8b1e9e21250c4789e85b51c18168e1de866eb7f7542e7b58868c59f9c775a5b726ebe8c8d148f830df37de25fa40262fd95cc027baae802609cb714b352c390724960d692aeb18a41dfa12647333c95baf7298715dfa2f4439b27fef8b382e662b2bfeee224a682b981290c83dc1763a9b4d92e46e29c2a1788c548af52a6dbb022ec2bae327390c522d2bf8b097ba9719df5f5ecaf8df80417fd67355175aa03fc4c241b0f66b18ba534ff07b2caa9ea16998fe9b2f905ce45360b718b32c99b74e09a0e3608ff6f1f8c6108a5c3cfaeb7f83f4b86e7fbb84a39d076a2117e49654ada0a93699641645e4cab7584ad4323255c7c5d023b0b50398475ed9a9a24cf0e2e6a83592872e482469cff7f94dbd88a1c361c3fc349acb84a635f6bc45d13db35430c108e6509dbc1b96df62c6a702b544e3a9703bb4548790ed175f4376d5005718682578dfc0c151d61bdcef84e5671672e4ed3a9f190b85232c1f5d9ccc8c7da9f77f84ef068b93188cde5478f6e99f519b819fcdf0174d060c2d40db55641923ce556119c1d99720607d9a2112dccbbdee2e84f689f65f61cef42878429f480ab0ac2f7f0152d28d55612e437baf4b7efabbbde8c8c6316178567a3258576c3279dfda2b2ec9617e0ae4d57abae74d77782a97427e5bb21c63cb499a4c31639e85bedff8273d45dfcf64b2e63ee13ccff76755925129c6100d8024480b6288faf96521a42d126acc9767ba9de67936efb9dcb0de2fe19407963b6d2a8bfdf7d3fe4daa63003fb4c8210e5643d14af72e7ad5363705e8cededff93f878051c2303ef4010285f8f743284144767aa7f54362867319f054e4e9699dacc5791bd4f35277aa70e526f3d3e3cdc7d1a6982a7f52425668493f222b34237d2c554e937ef863378f76bda84fb15a1312eac195b1db5a30d2b1e9daaa6d5432b27697ce744728fdd468318c4c9dc6611b8438b508a7335d7d0c80624ff31b231cecff62271b38a90c7ad38b1f8320ea3fab4c17c77dc22f7cbc2d23b4daa104bb0f0751217411063102b6b6e6d653650e2ca8031df75b41feb579edb0ca1902dae6ab53c7a0fd7a507a2dcca9241b09f9752fac9b9727cfba1a6e3d499a0628c78c9a33d6f66878cab64bc2d6d699bcbe900706aa7dd298b9254fe40be9f8a658fa83fc82fd7c9be25fb497bfa6357a9ad4c4eb4ed69a31ec911a804cf1b63b1325154ed271dc09c6e954bcd7d15ac63c04d2ffe4dad5010c6fd2167a57f27c307534b5e970efc9e8dd20749227462658c30e102923995f6d71d6b70dca98493fc2d137b6d4ec05bbe9d581a149c5efc61390f3bd8e2e06f00215196c05c7f8d8bf76d9b4c64e36ccf74151182f0319be13590fc6333ca49747a7ed4ae3e98b277dee828daced102630af1635cfd4402ada298b762ef3388946f155d651ee2077e9d33e1952cabfc2a581a3fc08988b5fff5816d0a4fc5eb1daea95e42f09288fdaf51a08d2ab2914b3f9f197ebe0f6e931a5e21045af8e3eaed34949c039f22805837234a9fa10ad0f95b9b65929d242ee28b903cc59fdeefa30efd01a208345ada15545e7fa13152975e4b1edc0620f645c15d5bf07c0eee29463cf43f564fca489052b45f928248cf7f18a2764e530056f27b48b518b9d62ab59b63b5e97b52ed5010a205b9b691b606fdca858b61749a67336bff4f87c19de9577d86d9e7ebeeaa9e68e4546bfd257c1bb83ebb7adaf8067a57b42088a0ca79f6e2910041f2aea55f2465a7446534a8dd7d5aceea3e57b998df2b9b45a04f3000d69d522b03d4c07f75acdcbf9d0e15b2de680301f79d56e08e1adcd5f3ee8f320c93e3a072f0a8baae3e6aafd81c8cd802ab6ea652ddc4695ad4c9b396eff775f2f76155c43f0f08e037af9ffd5d2c573d03393f1992e820f1d13ec57570e13edd5ad2c57bb0868b5c71cadc4b9c6aa50b07b8d7521f8a17e52959d9b75146edccc506c89a2d965cfadc060f1fd2b46b431d12155a4537d04573f3819548f93a9f18b96d6ce4e1847f9ea5c8cb99b64ccd252e9d2ae9775c13cb057a05ff348e3aa0afd51653fae1fdb838d96bc04689b35ed410d10a62280e2228bfeb5d373d9df71add37d77754d06bc23137fff35c833ebe9db6b9f01064a761bd4582f870d595b07d80c5130091fc7750e3bbae24ae073d2ae6ba651b2fdeea646a594b1eeafe7511b59d51a02b807d6548ae7cc785efd8c2c8f43a3994b195818616070705310562aa0123b0cb7aa99816f700d66b15edb59156133400d9275e7712c5ae2029cdaeeea6c0120cf9e2363c3a9d96fbdc48dec4a40e4a482eae5e61d61e11a85edb1e3fbdbf444fc40edaf8d513f00c225efad5963ea6017dc2da68476e9a6810fd973537b22a10c14788d76575b4e732ee716d2d5dfb67f7b252aff06abd0278a355bc4d6106f0bf16556f1d86befe36bdc39b9d00f71b1ee610655f7cbbe951ac0b77c8871cd4ec21b4fcc2618cf2a8f6db920e2a3b18ce8f67f570ea1f0073a86e6e12f41f12917020cb0b346596fe6bd43244f8e3508664587e929ece9e35b3f4ee78d13ed59fc44b45d73525e4e139991f9fb9cd6b562ac5c2ad421a1c4bae1604bbddcd29d804298af6fbe2e8d8aafe17a5b95fecd62f11ebc75b0dbcc53776d8a11b6ec527a686378b573dd39b592a1ce8819c9c771cc01fcaa81bafd59313f55d78580ed8da0ccf6f9b8634af99024484559d8b7366bb4b04e4b6e17828b73c3d3e73332afc9802d1f3d32a7933d547f3a08ab06ae803473b60845f1c82d1ba9e77b35a15c5fedaf24529ecbc82516fc6ff967817fc691c7b331385f6cf74928608d724333b506c42d8fb175b9e4843c8f52d9d91611bb4b8b4d397a2be39bec5b1c8815f8bd3424a384e380cbd1f5d2247de8ab2b744ea886ea36f3ac4839e1406e771f44a889c6c88c747f63a8dbe5480f840f7478ead3e63da296da7d5e2bc0509c24d8d3eb7eccc20002e11a04c232e451fe56b4e1927a0d4b9bc1eac55b1e77eb8c2c2309cb5a8643d5a182c075bb7cd69f0d85f9691c1019b227763197bbb6c22b087e268365d34dc963204a34cad084d027f891c4e8ea8cf030f4f9718ab055df559d630693cf7c1845297b1eab9f0040a92ee7041d92dff720ee44d9a1496fc3d67c8e1f34ba51cec0667caae34e04fc35daf54c677b80ead4b12b856eeade1be6f1cbdeaec12592c4b8dfcb346cbfa76b20dbb7aacde2c447b9e8ad2e7da3f03c7f61e3bcc3ceff21159f1b450d5446ffcf6fc8cc2326cbc96d941f49da7385c6c3e648cb3e39f768ffca14fc03db6341698c332e5acbb15d6a2a879a84fcec79a1ca82a63bd3d75a95db740c726dc38a449de4e36fdb603163e13c0d5c6dcf78a087fd38a5cf7cb7922fe02e2c29324176fda97abb66d93d0fa76c97bb248710b2cb134bb88451a38a51ea506e999cfe73a00eda95a46b2a95a56c5ecaca07470dfee3fa05c263afc826154bc1b414aa5432b2c3693146c0adf78cce32ab7d383e9bd932998446dfd39b68cddbc2d24644bec54621a2edacbe158885ef1aa35074f64ad0dbb8029fedd8d2f8bb6a92d9a3b65363b72b2c1a25c49692a3c5f2a1b006873725a0ae8e3945bed1c28d3336d437ed51c5e064dab3c15943e6c97cebfb51ce623a552b92d992e6d2c52a2086785732a06ba54eada573182e4f68c91342fbf02b69b2746ad146593a53f5a23d7163bb91b7369cdfb205b930a811944eb462ebf113f213987b239ee278922335386f2650d350590acc8d05314d61d83cb6fee22e388aced29d992a8af8788cd8734a31ad0a7429c04a14a01d4f017b2cf749009c10a5d15d7065a9d46521c6df0f51e590a9da38740b34a92f66abc0b6f38f51fd651af942a6f2f4437929ab50ce1fbdd8014b699a5ddab99dc288ef4fabc5adbdbf9b55dd907b22dc3a80a4af184430c661cad275006a27b823f4d5fd996bc147dcb86361c65b4916c2f14421cf2b8bca0d8ec3c11390b155f7aee916c5e16ba138d1c2bbdbec69ef8a36d6b0f033a9fb1065d2e9e9167d1e7349e2c0eddb9c877171692c38a528b9943b8f290f03a798290ba0ebe1212a4a8c3bfb428511bcd1af477fa42ab1e010370640100e99d29cf05cebf6a586bcf0c9ae14e7ed281c396135dbbb1bb87f7fdf6d51e84cbb2a66d6664bed5cb2f2793cd7b3b42e100d2505474c6856f6e9900d3ea7ec8abf90b75d48c58ca1eff6d200118bfbf9e25e94fa76b5524f901fbcabe8dd1cb2e6c3c1d3765c09dcdb39d4609c03d5c3fc550fb4e1e90085c1f69ad49762965681d26b8e5e4af9a8d4df21f1f9928cb73dd70b52a632d1a0668f2b29f54e40f1c38229e31942576689ffcb7b3a76b67ca857a44e7618ab0b8955812286d99baed19d626feeda402139ab58069601658393d3280ecdca4b4eb34f97f6c71a61283b9c7da2d74ab7982c019aa00118831f594e489aab74e496b5acba00828f581858cbc32ce38aaf6c8166c955f915f6a28476a5b49362cee4d801096bb8058b69e5904bc1363127014e4976b3c7b7cd9c7130d2fa0ecac2cf2bb8cf3e960fe9b2564291a092e5d318d801ed6504dd1f0a97d7547fa57589c57e83b241825c81b89c0f3aabed6ba7f89abd641505ce8b87239d8ce5aa1091e058d9f8328ecf34bfd08294ac2607e3201f9b957135a55fc5fc77f3363653fa84a35e4305232d90a7ec374ca39de3818694340cb349d3042dd37037dc290bde36db9bbe84d12c0bde36292f900a4c85870edf331a708bab528bcac7006fd524411eff5971250d8aa3013ff7fd018bd45de54b938dc8346d1b69b3758f0a297f6fbd486b0360b54ad41c0f62c84f61f56882106f1f5934e1f479686b0692fe1b300ae3f8adbe9ac47d58846b889ebd1fe42a9b3c6dda44e3dfe3d976257310b571101c2288e81a2dad6e0aae7900941975224e7f0c2693277c047913f2b24b9c549525616107e30d31320977f9f17e9517fa0ec081cea1b3aaf6a7041e40b5fe933dfe309cc47dd1f101dc937cb696c76c625268c605851f2f8f4f71e603067135a69f100cd0983cb3ce27dccd5c557c394d9560867656e5baca2b39c566b4eb673eaf90708cc58d20c4ad73b85531585b86d4209be4d8ae33b0a64c751546f165239144ce749befcc5f39b7c54a365ce80267b2e0cf080bb110277a004077d201980828ea302709a1df8cd1c9928342f0286f3be2257e0337601d022e4518efa90ac7db49b57d8e6adcdd5a56104437843493f108973d2666569b37eb54ebd14f5f929f47f4270a848d2e06fc081009f00443f5412547829d1245767ac1358f5298b497781c8b47fb8b20d2390af64f70873c3cdbb743c10c071ffb5059d70a08ff661bfd1c89fe16b458dcf99380090c18596b17565cade98d8d31be10b072f82cdd8150df8f749aa520a8b1700987910108a44fe9da80d80ff64ad8eeb1420869afd6d30e7c5429ba1bbd31fd22796ed59aa42d01e94f0492f94c23123d73678de76e10d5b95079d14e3e02630084afe95adf93bc4510ecc4fa6d541455e9a94bfb5bee4062d52070d1d57787e6c341fcb4729a627363534ded834d056e88011734d0238f398609c9dc7f8233c7bea644b753ebe7832dbc4c800413e8dedf074fa930899b1d5bf79819f22dc2d94e34d93610baf2efe12cc3a8d515c213a39c6db24be6aee672cbe61bf86b6780dd73151382980d081d7705562056f7378958af0cf653271c76de6cf8b7b3e33c2dbbe467dcad6e15af98094eb988b4ef5a781aa77b7e899f24bb9b8687b6b44aeced968fc3a3d69d81da283d453e893721018a2fe59458db155de9241f84104c90d54aa30c6a11be5815b453a8ab4e984d556ba0fd281cd91aa708fea78f86dcd5002cba13843b4a9c8e87a6365c7a285c1ecd2710c530028421482dec417a3f826863715ee9fe745ee3ab7fe1d20c03f6a1a2895a6f5c33a2a635a380fd57e7f221f98c1dfc991362d4f05e2ebd81167bc92624fde9813461dd2d8020dd4b867ab84e2b7f700e3e9af4ae191f36edd29ec278bd55cd1337ecc2fba25ae140f322f119ee2128a5071ca9c54c1022cd8dbc0c7933e111a49cfd2ba53b91abd1aa44d935bc41ab21b2f5a9de914944574641902359ceaa6d75972e20b4a387b4f0b926abc6a551953587c0e82001a50956821caae3e6c03459f1417668394a869bc75f29fe9ce0ebb710c312d9b8177aabc0d461ecdb855fc2fff077fb3febf1142f012e2d3241b76ab9b2b839a6d1fddabe2dc3ab5a59d5ab43f429140b0654a3791628e56159450f9328990c133e0a900597dee421634383d9656de50993ef07fd88dbf73fd62c56334ffa57bd65e48162566449ffa25dd5af7bc7692b8f5f226996bf354e4457aaa03c4643325fea94da86a823987b665067ced5bfacfd29d2eca5641468848e77f4c3302ce11cc579d88fed8e7d9b0c450193489aae7bd3c9db3744285a90c32b60bc4ea5bcf9c0ee83fef3d37ef3faff043afb5bc41456c1f9add910731f8227e9aaa58d3feed3162cc1725af6b2845896ac48dd45dc37f501a870e89e0978d24b16b54a90af297164bdd518ad85127c0d6ff2de047326fcd30ca12e32dec325e97ab21d0934d9362e83a3e7f5c57ae7790b3d542d0543f44137be46b86a7f56fa26148e7c2c0d0b1340677e80fe24aa193945ea80c58f06a534fff2c6618e0da7281a327c584cad5d604f7cf110d72ba866b9018f13ade89b935ffad357d84bc800ebfa20f782642aaeeb913a6d5e8b6a7c1c539288317b0652a5ddace6058ade7016756f20a55437c33c71a0c6c37bb2938b0259556a30cf10dc19bf533c239d4db83a7639f8bf8714ae46a5530654e01ba25d639eb51ee11d0ad77b86212085acfae28d29bcadb934dcc52aa5b2d812d016d108febf09f1d6d3c1c3bc18c27ad77754d8ff1d2802422407dcbc23af0cc107392180aa62c63a37dd022e3fd03c65a09cb7bf717ddbd458dac74307f5c83674616714f7ae0b18baba9687b736363439b8f3bedccc8629c5e2e849db48e571b6f371be7279756cc076efa63d545df9048286496b1828fdff6f8d3b1f5972e3801d06c6e3c84c3c8217cd19783d57eda671b323da57d1d9a4504b1bf715f5119e4c46c932f60386845cab89fff28f736932dab8b9a79e70709a561f103af595ea98705cdfd1e56caedc0578b12da1b32f1acaaedd994dc01176c4b416f1479f067e348c2353f182a029e238340284a61b1328e7dafba184477993ca97f098a86ac0ae936a2f734bb64c5a3dd37c56b32c549dddc9fd1e5581462a23fc3e7f0632a3f51ee3cc10ed899852af34cec3cf51e5232d53b5243ff261f7925277611a53d69d14fd81df99fc18d3e790702f0cd7985bb9d826e0982e53cf4ce0509706fff4253988d861a343bbce53e491737204eb414b0043b6a673352e2fc27b51008710ac044c2d8750dbaaef460d5afa36f225da3559417381c872722fd1d8fc03d67ac39e2b81b2c2f0d990041d66031b3143e7bf26ed562aef1b8e410a80e897110cae682513eb66cb029446576dd890141b688029c8aebe62bcdfc640d72f2b4f73cc64e796ca32a6b6621dc04ed6ced1b7e668128826827226fda073658198ae76eb0eb4a8babc5ec25cd545cb2f0787ed69f0fa8c71c2b45883b96d6a215ea92756a21b5df4e27a6f93e30d90f28e509745c2515761d943ee41f325847109374fb77c9dc4167d92ac6e1cc91c7c97f9f57d6c56b9cb9461468a50022567cdf2e0ac1bb2d5faca05a80d842f7e2dc4b3e0a3dfabdb6bc6705098bd63aae3530fdf29f816b66065904e4c858d8a91f8d1e7e1ddbd3b6d44c1ec3889311b78c21c944de88382ce80a5bebd8fbf790c35f6b99183352bd175ac98734409058d507058fd582908883c92b32da9ad4e1cbf03dd2b01af9a3ecfc7fbf6d57de026c9d43726e25e3052493bc343ea4f3772306e5a00bca55004ecb51c38494e2cca5192d3c5962843ccfc07eb0e0cd0c1518e52e818134e6c67b0d2f743dfb5fe28166aee2b84a1195799ee1661795f5941867421d070fcd6c456079e4f57794225a226344a9b85c7b0d827f19e52e2f96cf02c171450863124de621aecf4f0a232758f42f3179217311020c99a7292f03a406c7cf76fc00d44ba2357fd18ab2b56ea870dde4cef1cc0304c5180deb2e259ac1e456b40cdf48557de034ea0cd9991934842bd673dc02ea6a5a68300a2ebe1c4cf97812c7f62aa79de944b17ba99241fe751c0986959eda4c776d027a81e1596dd44a9fab1f3b1dcab42dd22185700565f996aa45a8b5266a3b8764f00bed913492e1178f6f6aead2f45a2c055e6bbf2ab5405dedeb232bcd8a2a6ce227ad8eedf7018d2c3a7998b85181e8b6cb709dd9d573b208a384ea28698d65bfcedcf2b23b972fffa4b6783df002fe6a9c68d88af4d6f03c2e3abf7145a37940fe2b0ed6d47ef95f92dff4d891017649c083a2ca985f0bc4cfa96fba0cf4688a046ea2ef890985c8f4d251469c3bf022b2903370179ab756ca45390c77dd2e322ea7c0e43c9f945864295d775768432888851422fed6bbd3f1e29c352db465db9cf4d695f1ff6be34f20f95ccda139c6516830ad9028991972a6b09688d8cfa03dd9b416e466fbf230b7396ff39c7cf649a0adf8ce41feb852665d9df078d59f8784ae1967b2b2dee83c7560542be1455ecac5bd5fe2b475f6e260fc2afb2e3d6771b44e6950e054d85f40904b3792d02aba079cef204f9281dc7e3b704032fe23387daba9b43d982df5cc0b726a3b0dc8ebbf629c9a1eef220dca7a4a541f491d7e64b9c68e18361a80dca71a7e4d2ba084baf9c77b17bd091ed1e01af01adbd4898500dbca04d2566e3b7b5ce55d62214dbe079f5f7c01f05962c169d9aa8278d4cf10b3beb3bcc7f81e23065cefc580886e7c9fed6ff87f423cbea5f24bd8562bbc82e4355de961c4d6146c31115d2dcfcf110ffa1270ca6d5b000f246f140327e8d95f5e46956476e50fe866b86a5da6cde804c1408b57fadceb212f136f57c9a904bd9f95fbae2ee387ce4b9cbef4acc6dda0058f59c430d275e6698090e0b60eb5a34f5be7123a1ab10e99d300089fc4e956868b34716a6fe5e6102908956f52e9abc3213ff19866091ffdcd25535861fa8ac6c7af19d57ed7229176491d4acbd929abe5a4c4af073d0a3132d5935bd81bd1b933e665b68380ebb4a7e50b83f3807d152f2d8caa0fe7061ca16492f4015ee225b966a0c9dfea8e03be755b9e41a1885f8eaa6bfbffbd530bb8824924d16442df54d3fb42ed7b1195897574a964d3d34c2231685b793437d7ebd5ab47567ce589bbb94a83ec3bedd3b14126c96402707203ff611ec324699f8a50d25c8e85fc0ce3204dcd34ed0ac7d9dc46d4ec6182957a902b940b09acd665529e933250e91023842ba255a73f04b65f1942adb3771a5fd7b7dab6736b65d5c1a2ebadcb3ff0f66e8e2f2fc448bb249a69bedcd533eae5191e30b30a4135c7a8de9cdb3740a03c05ae8ca3409a43814044639a4a7d2d059f84094a0f3a2f5e5e7d2087aa398586a613fb9ca32b813f73d3993c014288591652eaf9b02375198a4667f600592a3ce44909b1e45f8defe979125793e0ee053a1c4606f0d15650b593f4474b6f67847354d4f927e5709dc530afdf40c163edca9d7b955e7b2b99f59278d537ba6459a4b627662a65756627b51ccad6b0bef950b68d80c14c291038ff3917195f3a85d8360485342f06d98beacd24fd42d9ea1fe53f83799a6ef7e3ab0d9401c92435a05cb7b21bb7e975a85afde75564e68e5e87ac2409d3c1ed6e2dbce342c19e200c99383ad33db087191691649de83fc090104fe49db80050145b9df7c8836755981e27f57b12e3792b91f1f9850a0f05755914d5663272b9ab4c6763be93f4dc040293cda8da93b1c94289c7a6afc0f09519102ca170090136252e468e3dc87bae3a4b68954487cb50c22fede74324c7c2af2cce8c9cb985762823257041c2eea7bef69a8cee00a6e0d2f7db4e8cce46e9b7bdd18d706050a4d33707924a2d9a7b2854d26009a1182fdccb6b218b8fd320ee68aa03ada1631dd07be7474dd6ef68170814edde9d6396368010bb15e0eac17df601491007bc21ef3fe698f25cb2333e3eea2afc89b49811de50bdefb01da6aec2a8ffd0647e4479731db19aa8fdce91b2ff95b19a8d7b9454e9f483eeaa3f7e167e83943b89ba1a75854ee9393d1e8f9fd258e1d3d5195c3521e251d54b2a2ae25bc469ef902504637395b6403c7e102dce147926e3e78a158e36c2990535f92f94128ab7323c95f99a24102efd350c65ab523008a38faa7a9e5a8add16b40ddbca2369d5883dbcd0ffc3e0896e65a10a23f566f63df1193549c1528103498a85fe77bab75e0fbb0659021b25b6dd608f82e9a1ba393558a47af714a266b93867cb4fce483541c5f11c35d3ac728197778eedd1c78fc1fc9fbb45be8406190171ffffe5d169a10016032d4757249e995fc52c8922d97c1ac6acc5cbe73e3212a37ba30c91a74f1157923b04a7580bc2ee7eff5169fea5ab514e1fc53d45193dd41aae8fd83a4132204e3f220e577171bc47b52e999f2f46b83e55f6fb3761e475b11556c34a1b15d7cecc08a889ea4e135020ee67288a40d0a492aa02c702d4451f0d294899bcac662b261614209c3a54d710f97357e718e89cc44c947974c3c46c85b39105669416a9a51568a66b6626118512b6d190bf01653333b13eae6fa11f6f4268751b642300e9b3b1bfbb3552445fbea8fa45f0b1a6e23d7ccbbce9c054c14d53f47a9850f522e782e5668c2ae3b67ffad1c1298023eb130ec187cd8887366fb20c71f0d67ae8202086f30eaafb1908bb59418d557e5ab5a87976bc31023137ef418e37c494352127ea0c0a4abaf2aaa24c1826293a0492c8b80906f57f4adbda9b3980f4c2f1579710ce54d515954d7bae413efe9668c02419fb9132dfd56c76166c085c8c783391b69902925ddd12f55246b114d4f17603ad042cf813c585b3e50cd7e4cf4166250959db19a3a624f447c5259b4a05dade545c9b1f10d55963d3f66d8c5230271d6023111ca6d50687c79e3b8b9d6368a8ced8561f4fcaf4c1004bff0405bbe049891c3badeffe6c0dd829b79d7bde318cf4fb8b7db8a3900f8c93fed93009fc10341ef9ca4692b73e2cec526bec17a01e2f3ee7cad7feba6999883acf0e575a99e7f1d2a3673a1017d72079fc416e3a0b7c6a7a20b9004a31b4655dd61281558cc15c55108f634f90fd7b674cc4a7da6af0524f1631ee2831c33f40a1231493c29ec6565fa66c7c37955367102b3ce19da11c60787dd543d12b66cdeb1aefcfb5efdfa7e26fea80603aa8bea58bfd9370a4bc1193d6980b6b801d2a92e432ad458a021534d5c2665b078109308115c19c8c4fae130dfa8a6008781a369fe4ebcb593ba15e83866fac418b52f01eee6495c9ed2d6ea14c584791889ba39af99c78493524b72b05fe0c2f7aa3a69a6339856b931992de800cd08674c2cc13b0d864c348311ea371e29c76077248f9d093eded1bc3712f2f38ef10d7d2f64749cb8a626fe149a71da52e0b65d19778f7f01c7b01fde62f1d559fb87b775e7d0b44bc442a15fc2a3f8ed7f8b989a81f831ba3fb400b8441f814f4c13b49a41855342806058b6c60069756dc0f4da2b75701bb431fd4c7af0af4d431e82b1c6c648d8dedce1e5fa5d7ecb33ab19e24d15815defcc848b5e3eb01bc7436e3d21296320d66c4fc99a01fe96b6c51031dbcb61c0637827518e375c9fb3edfdb5141a75b435f5f5287b750604247c1c146a44e81bf0c4d822f8752d0ebca678d40a4efa311a6317c0ad65afd9fe1f0760d4543d09ba74dcd65a418277a44177388ed8c08892fef3185ef7b2959006e2242f083b7766637afba3576182ab4c97daaeec4c73acd87721bdca376b15b9426edc835c66cdae39112fcbf43b4116addd241cc73529bbbc627f0e3fb4672518d455b7c2d29454c387f2d0e83b1869504cfd090b3b67a9cb523d3d3d70b262cf6ec7e1012b1a4fb4ddac06ea63c91327e975dd8ed0ca30120b730e537398b4a797162c5fa2265d9490b78dd501731744ea9f6b581a03ec446902d3aa186e8848e2441ee6db3e0034421159796e4db3bf21dbf004e7e30844d28f08bd3f7d18057c99fad4e55c5a6aed0e53d451bc3b088334d724accb53f506e7ae684e66dc08b7a84f9b7dcae214593001cf737c4bd3ead1a5109cf9840fb365c5929cef3348693491223f9ad600bb9c4c4e33a68f143f428cc5fbcd2bd8e07f8fb152e88be251a0a3c61ad990f1e6f87cd8cccc39398ea1362c668fdd3254f21513151805bc85cf38e9c5a3aac5cb049c31eecce958efbd70b442ed9199a8fa0456fcb959f7152fa3132a4ebaed0f81a1e68aa6ebb32acc6cc9f24d4140d6daab35d2aeb367173ee7d6d5fc67884c42c91fe1dd2c70ee9ffe6dfca8330452ed151830e5e17da6fde8f2b39f2c560bc582f002fce0f24e6bb528ecc58cf433d3afc03d18fb24fa279c06a8f34ace93ec333754de850085f4ec180255e00d974328129bcceaf7742a110d887974baf04e6ec7c7ec2e1a2a9f760e28f00d736b9c9eda5412f357150dd8ce0dbc847bba3f362411e5f9f74d02417b6c7207040bd77bceb6bf113e72b91be4141087d7f44ad29e9c412122d64705be3e6a0f0082708c8e1ac23356b2427881a60d6d8ae146f8015152656ac3b7aae740c64c2366fc31f4a58d70a64e18a58582cfae9ea60f823920858820ad35db8e6a3e0a7d2135daf8a2e8be43fb05cb40f59a5ebdbaec8e28e08ccc0bf10d77a785f11c1a64bd417f07da956b1a423dd8788c8f9f1f2841489001169cd61f41ee378b710c4b3f4af66877431eb23421dfa413f78de28cb546d3af52b4871d69bd35337a4dec2c250e0cc9e4f92dfa5d527a63c713d7da48c9cb4a177b6de5b93431682e9315ff296080f27477132ee62ff71dd77f4eef898f613825f6aaaeb4bf4ac6e440450c51e716db60d2092204752e55c807fdcc9b8ac277ccf2156528b9ae7f4c6ddb00e5910d513e6cd33cac90085d93b325e286bc57731a12255d58998e8d0e832427906fad0d47f1485ab45c31a3c25ed106892d3b015d5e7def62d2a0b2fe53194af43d2164a4a3e3dd6da17c94ccdbf0e3c6090a6032feb86a62225f0911e2a07ca867f82fc6d4007ebe253a06d7eb2db9ffc8163db6d78f4253dc1b058265319ef0e4fa7e1110cc06953f3c2ba141f6e498710da02e3bf831d2a7e7f08c430a8241105d3b705386a5dc29f84d9cd5e741414147ec2c77945edbdbffed5a7cdaa71d09cf2410cf32d6dd622a2181959ffb0e1260c76d4b5d17d5cec545873db7c8b1127bc1fc698c353900f70647753720203a833f92ce927d5996cebd6d6142e5eb695e663d22a04f3d71c88b1ef73b9913e697da49fd92cbc56258b74118bbedda1314a975cec8d55d9deb5cf8615842818a3b3172d0e564ecd6a3e4d4072c9e379fc1ed44e71a7a51b0950f438ebda1065e850250c3ebf88031aa896ff38aa44b51d055c6a1bb099efeae98825f1230254d000e8835984d1da9c7dcb62eb77fbcc0d1e8c97696d6f4ede14c37bb5a91c6b2233ec71e39a11ae6fd62c7126a5febabc330bd51e31ff009a44b4a53c730385e8836cbb88d731710aa1c0b2d5587e6898e3b840ac2739b0c92fa60fda162f07bc226bf7c3cbe93d88f2854a30601fe9715cb07ea5c12866c37c5e7b76c06f0ebf92ea8e987cf7bd546fb9276b01c1c8f806a88102c2e8f239022cc360812ca4b796fd3b4697c6e9e152ef02cd0ebdf37fcc55acfbb1558620786e531daa286f131659aa76f488ce464910dc4d1b1f81b13389d6d81708287c5f65aea0b665b72bbb982e53463038933d7b53ce873c895d760dceff9cfe5055c00c2d460d05a7df1a171c6ddf1cac5c583c51a060408f8ee62e5e988304a7b0ecb8d88fc869e1e5dbd4dfec11eb416f23d8656479fbfb4e81fb814a4ccde16bf9fdf4c833a67af1872f25dc614391feeb7c687e376c5f0848a371b9785eafc2c9e220e01987d01db71215203152234f77725934f227d01ea6ee66f908a9b56fb2afe4687a4bb70aaac3cb85596d0c7fac5584eb261728efbde9a61a69c6f685771c4363669ca98718fc9d6702fec05cf9763ac1471725a97e1b544339623eeca3840f0f342a1e1c88a04305f4c4c9ee4bdd4e5447a7c819968460d1597335812c24aefaa4c91e86ef717c4a6ebfedb33599984eacd757d118f16eaab20b56cc04fc026c59e75b321069b3b8a992cc5c3cdd0093cc7ca4a8305e293ca188d8f78e5502c1cd58c3d42522eee7d8bacec4b7a402f437801c64cf2e921b4ec110e333f077361993f9f39bb3945a6856dd5646b98f085b3095f7f32258e3409fcdd77fad7e505a17d984cdf50f1e733a48adf9faf67bcc4b06331a07fa7a58f57f4f02a38091872d7c8250c1babcd6cd567b72f755e0fa2622a5cd5637f0aea034766fe78be31cce4705d6d1bb6d2e5ebaaa40eefc0b2d7a6085af87bdb5634e1df7d2277a498d3f307e6ad3de53aa2738140e18c23441035c4b763cbe3b18bd5f5abb99a814ed498f09deb6fdf685176d196cd17c9d581ea4cf09c788e7ce6df11c3cda8387f75797c6ddc7476ca331c582ff62a41187cb9f8b46fc250bc6a7bc385c927da47aa39b36791ad272c3abe440ac913242272dc57b2622e730f8f4754a3b6060bbfcf400c70c56ac182a5c1b73d557919eae427aed4e9e0bc96c8a821dd3fced3c6caf2744e020383cc4017a4739de9e077d733d788d4f4634869a4b4bd2e5cf100932e6881a0051c670a0cedd13114b26ffb776f9cc0833c6a4712cc0573760371a2536d0d717da678a12e192a78618615e22f0cbc19f809b52ab006843504e1ce81869d12272629075e051e11bfeb183606a8f81950e861fe926b441733ddd483bd9c2b5aee6e043a7bc551f03b9c953f1ceff9a50945052f08855306cc83416e1acb91a9942c313b86c5e9a18729c12d7394085c18a1fc52e5ce3248bb9aa433337edd59bf50a8bd41427f1bbcb84fdd7655cded29168c3fad801e504a8ab746ddf63bcbb0518348484daee922c17fcef02fca1057f51c2a448ea67da279f720164887fc4a52f68f25021df452fa6c3eb7b329180ee8c8aa25a52ea9ae6f8815352083cf68fe6d7ce0028b85c4e964b69c6610382998bd1bec55cd1e8cb6e0f676b65d8aac829299b4b60265e7e69499e815edefb18d1d63d13972f9caccad552dfb63a0609dea93b6866a2550c16585be87e556a6049d9a507650a33ed0ca4a5704d05c99a85b3f0d60734dfab55cf53bc5182d274861c95cc4106735234e611ea6f1c643af4a24c74a6b32352d0202d7c41626294718b7ae59218bda005a34dfdc1753850e22f9818e4bc6c0dfb4d7f1a6a3321353e60c23ae71700a423ff05cd3b6d11cb024026dbad242c3df7ba175d37f01b37657f9147537fd0879078d484d836cfdfc0eb60c3789cbad5634ae7c36af5ed44d6ed8c50b6233d03dc436cb2d6b02283765347fa843295b6047f485b870edcc3fa56fd6961630cb1ea4f1440315ff5f897c8aee2b592c4bf8a952109728fa12b7225b5fecc8ac09af1988bea51705d386b3a8e265664f3c0154bed731f580301f3eb42ba325021af240fbbc82ebdcac73567607d93649b96515a9dfb2d294830b6dc66e24c46dd71f90c64539f7afc4f390d02f460487f5eccd998db4f7896bc0ce6889595cfea9f82a746a898e1162388b2b26f4690588cf818de4e6d76edd9984c8cb966117b7df4385f0ad1327acd53bab9ef153e15ecb90fdd3784b4574291578bf0bf9ebd736ce9e95b765cb5dc1a30e22b56b045d8435a902c01847fc5b938230b174a968536f1a3df920679ab5d9c7cac3e7aed53ad6aca57dadf862d65c9ec8da7eb7f7e44673947fddf9b5cfbeaf53b259bd556508932de387a6ce2b04ea14f24765acd3d8ebbd614431bbb702fdcb33fc7e8e035ec5ffaad3ba4bba43d2288a9ee9b6d43ad24653a51b9f5db7856992b264127769a7319ef867ed82a844d1c38d4cc2ae65139a72466f2f14819eac939d6346eda8a6767a0c51d07516f54aa932b592a221a8262dae9085d8634e86d9947baf1384afb573d4760cdeec6293597ca8dc323a66d9574687ed5c291dd1417a47b65c83607adfba59ba71948d17e6b78b516915c6146fda63b2e64ffcb514dd7b10713f666f2f52e1cb1c97fb3f03e095c268283cabb0095f6e3e28f9f865a0084f18005edd1a110fc9024aa3befecb43a8c9023ffc0a4339d2f5070a92243e5e21bfe254bdd2ddebab6f0a7823ad54d69fcb20e16bcb9e0cd0005ab5deac074ce25c0c759a52af189ab322681b1303d83f3dddab8a9f02ad32578d2518035048588c983129c9a598605778b71bc9f92a316c66e1e5df1d5b5a044c34b222f2f79095aed96dbaea784152b328da83f0d9aaf4292ab2684f854c5c92f48ea7a450f884d46af5358b10b2657e23d77626ff53a9d14ad2daeccffdc9547884457bbbccbe872ab00edb9b7f0294682c5535f93530f8cc424f15830de018462bfba2e6c6c0f92cb7298328f6320b45ce3fd0db4d1dc90263427642ced9aeb51269b988d1cb5156cdec46c2777a7e8891ae2bd782ac65f2eedca3a663d7e64fe5e7bfbe2226dd996b8f006956cc7f4698a7630b24127662187bec1600f73941622068c3a7160f2c281f1695e65be17c9d8409f1b8a8bf27d5fa49f0e40711c59a59255c561e0432e9a4334d64373edeb26a2c1d56005316921fca28fa9df5306b40d15b591b9a3ad62422669d4df7b34c762b940554e0fd2744e0fbaebeb04eb49ba3e338c06ee675ac1c8bda960e09d47520129ed8c3c1490f388fb9c95e1aed964017a464457cc093f9851c9a63fc8e7f6b7fe596d8b4f958dc2baf76cba68c5390ac052761203562dd1ede487523e7d8d3574c9464db5e2f362194e24bda52b3b359712d2dfc5aed065eb334f1c055d4591efbf2d999df3f4814151d355c0a35a4956e95a417e3edb2dca53f328bc2269d56e0a980cb24c7c206d48ce88a73eeb1d5c783350d1baf9c4b2046ca1aa7131d609babc135e25f1c3724ba0841cc3412c3759ca2800d72dca9458f437f6064e0f9c25a10de42088bb06f84297eb721987a049de405deb0d856925be97d5b0064986928d103ae2d522e03d97e749ac3a267e019b1f882b38205d9c2690b6d96fa7523c81cdae0a92e493a44f498e95dbdecfb93c28506c93868b752091c811e032422c397a4526005f96d18607dded4972b0e1c06143a2bde6ec7e73e4c9fe6ed97d1cea5b7977aee71713bd1ec74152ba63bd650615219836bac8a950e18675bf174c56d44317825fd1f6999ffd6d402c17867c226b0744db3c6007ee41bd7cd3e2ccf374c835426c3d8496e21493b9406c5b1df9ba1aa137f968a9b962051dd4cbff907f1147130fd32fe1c3f094cb87c968f48012476f37f995fa7a7107c3a36bb658049a0c888fddb298e6ea353e2b856aa420eb5278d2a03a4d33050ffd4904835463e41c6149865394a6610f16e09a3bfd2eb0e4061c3533a032a5a0c0385e7d9731f75863e3b13b2aa5237313ad8d539b4e2682634eb86c4df0b6b7a02429715d72cd208e5d27c8d8d8afc501505106adb8a2fa393f80c2f5000431f76c12052efb0692b60957375885f53f506c48c42eb4d5d7a06defaa61eb33684c45b41efb89879d732cc64c5b4f2c39e4dd317d198df91e1719a22fa16497a45b00a09fb79c347baa92facc8c46ba8eab076d51267834a600b4c89f5da26915fde49c6ed595d8a1229fb4298660888d4bd1350adbd6d31db02ac350659525599a99ae095b61bf495c66f7238511fba69e44e7d128816276aad65f817dce675b25acc68891db925ea2b26b67843f43788a162c33337313001fdfbb8230fcf2aec0aabd0b9d221f3a529f0506a583b0c7f08c220a1b73ef7767472ff8b82ed8359ce20928fc316eb4d03664656aab8888d864823b6d40f8202ef8771ae15df84b301dff7ccc819077008f4a99501335457bdf59ac71cacf8fe601344761bc805dcb477eb9f193e8a30a67b00fc4ca710c9047a7ce1602975af7464b12b62552beddef4371a04bb21583c41fe5d73e8a01718cab8eb00daa068adcab15c54bafdbac3ec85a37b5f5f557c75f8faa4899a654a7510ab2ed3fe175bb4d736cfcb1b058fdc0c910bed318be8a7828427622bdf20f655cd32b2b1e8dfa5ed5ef6d0d1d14f8ad5aefafec024104322841921f0681a54035d424421a773a3b416e586d4950bf23aa662420baa62b3634a0c965eeeda625c80285bf10662d15a9119625733cd83d8903e97e07990753c7431ce13a61b9772639ba0fb54a128a0cb43da1be260b27f58f28c092919288e786d0da9879d9dd41254ea065846b49cf25223f5c954d8a10fce69cbbd4d5c542d60a56aafdacb3420ca2e277fbe784f0305546ae66ad4187ec8c689f7e9fe3a822143a80f2b7b01cd64a2b6219af60714fa8e5f2cc256d63faea55873fa4a340af705b00501332ac9a8e1e354986a68f4d769f8dc0191e9ee494afcfc1fcb9e7a06233d9912044f39a0a607d42decc2f007dc2ec6080eebc2c9c9a861e4f2aca467bab5e34c0e9f149ffa5d094bd3b852fc28aecd815e593a0e1cbe86d8909c9046389e3848eb7ab7c3bf60ad1adef20ca14a6cbb170aec1f159639ca7fb66e0c4494b467a2ab053ffab5ba16630ac95c4c19db8be1f74172ae32b557eaaf4534d174975d92006e66ead8f32a94ab17f26a43db876969d36b3177831fa67dd87aa829530a9b48e795b153f728d04209ff9d98fe54edfdee382133531234560beee5b8a5a4843f03a751cdea562aa651ef0c03b9a4581d6079c052f4f9442b7b5091c2921fcb7139d1fb9a7755b0c370386c14520689b6d3384de6d9650fb3c7ad2fb3fab577f1921db5b00d3090cef809bd61dd3af7eb7f4381026228f035ea0b1019dd4fb3102461d0faf4f2b37a8c1726c271daa87df11be6128fea6812ae957004c5f795e1c74b26b2168f2b1268dcb1dde9aec46460da106608bc5a115f3861109b2536624f4b7365e11dbb8ab9d373d80995f21ad64772bbc6551576a10642c75537b61bd716d8d8641f7a718acf5d6ed22e5182312deeaf534633dac23d6a7bee8c1a3899d3998f7b64c60b68e0e45643db85ad6b6a9099aa110dfcd2394e2088ca3f42ef6c5418b1cde6bc76471a3b3c542a9cb8e164cf5ec2c8c949696fccea56e93643063719f3addd8d4d8842c473360fca000d9cb84cf761eb783f5e36212d9d08b612a5331b08ed60f6064267cbc8e958d6c2ac7d4f4108fd1d6748d6b9202d86f66cb5cc03a84eed1bd5ae85cb0486183eb82ed82b8fdc7d4265d5df0ee62c853152e404d33bf56dd996c1f3ed37ce9fd18176c4b92f32c182a71db49fd46cf046c17636503b0ee42772b55f6737b9d81e06f26e079fb317f8f31f730e8e41a0206dad23fb5e0327cc510ca5e504df84cb496c4f5d55ef970da8f982384a0a38d8f7fff78425885a2cbb9f90f6d39f55af1534680deab3aa90f6c668df33bf305a47d8c40095cb5d358a926a66880abccb032d47815f1b68a0d7e7c5743c9c7414c4276a60c60a10f9e401fb27c1fd3e16d7145f9500ec52a58ffd48480ddeecbdb2d87d71fc1a264730eccd9a5046a262e01181d5bb114e5ab2ca6a2c70df65fb6947912b2e56cf39ccf92c788bf4cd8b64ad49ee1f148b6f8024a828256899e439d1eaf7ec0409a73b09becc523d766ae29af55902a3c13034ec1851a58c9f6bd74b0d697450dd0c254513f899d8f41aa6d16d0bda4dc990c0f75e24f071ecf4a690309c8f5c84a51dfba773c088b01bfe102466b61075a0366a69a9416689c4db9d0722efcb3284300bea3dd3678a9e6036961c20bc0906c3234e328f25bc2a712b53632b943379bd2092126aef359ed006fc786cb3ee640dfb1c25f9fa1b4b43aade09a6063af3638e33a40ad4b1a3d9abed20cedb983d72d9d555ce102e2b9223e0fa2bfefbbfe65eae424b9d1bbc429b36bec9685700684031782ac7db382a527b510ca80a7598eabb3d12116905504efbb7e16b9bd9c90a0e2868335ce0d2934efb779fd108c80ff78d50b8129a95fd2b34475b7c32aa6ee90545f849f7f1693e070fb6b60c38a53a5c948434770b165e2b1a57ca21a782c457693c204daa58f924e6b346fd75b6a8ac1a2696f91ea1c1acf57dbc96f90c6a272b901719cf3f1713b412d98ee117acaca1881aa63c09f70088a955f7ae2fb03cb61f069a5a710cb265e491aa27fa41e6be838b4d61e09bac83eedbd683ed7c9cae8991f2bd0a38d63fb1f08b03e6e2fd5b7425738fb10f4179932983acc4c446d15f9a1172788b86fa25c5629f4e63fe225a84903d08f7fd9e245521d932d39b63f6e9b571cf07897ac52059084d181b8c11e133134cfcb020d737aff80805812af267337d6955f8d33e2ffe1bd93ce7c8a9cd85f8739fd6359415e8d9ab1ecca35851899b795c2ea360eea43928d3e9d9580c511f3c95fb7132c77f5de3f6681b693b58b9786bf12e2b25cddcee33b54f80e36e1ed18933a071d6e7bee93375b305347b231154db8f84b65f0a2b802ae190cbf10363df64ab0acc0b697480905ca00c20be1443bc80e59fa07d750f683d5d6d5f891dd5119ae38f6cfcd86554a8f8f19762d4d9f931442326e6d94758d39b62d660b726e246d797ad6e268cc00d6e42e48f7be2cd8e0d7c38c28580f1e46cdd482a1a5581a0f9417623edef043531dbb5ddb40e815224830945afbb07ccf8ab648bcce2be081076b1d76d50cb896c7ad6defb367a82a1ffeda2e628eb0b666bf012d9b32eab3762dbb46cd84926358e1bebbc45dc741d499386e6fa8abb878189f99a4b85121b41aafa958c5fbd50f618c5c65f9b1862fad85a2fe6b63a90baef372200659a47d1f19cf5578841f035e145a98da9abc6a6efbb80976f683511722f67f7de11e63eff00950ddac09c843567031c6d5c2f542eb134955bf9d86f5c5a50eb60df239ed5c35ee17b42e99e9e746e5ca3052e2bdc23b1b9e0ae69ea567e50aa21f73b4a8ee4653c7b88a4a1a1f4ee9d7cd9e2093333b054bcce1d5fe74d726f481cb2d3d2bc95a76f88539d42bf113c76fd86c547bfb5aab0851460fc30ff98695e437eeed4538f62bc6f8fd9544482ba848595d1af7fa41093e57fb9cb859c6885024b4a0371dbf3561736e833585d04c4e47889fddeebb4ef50692150f5367fe41233542ce7e0ef55f910148b9bd99c2ed847853a19da98163e85e6aa5b2d726da4251abf15611faf47f3a0d0f6d10a7fc65c8397d2b067eb126b7212bba99c82171c50c72953a13fcefb5a5cf139d8ad1e7d35f30dca1d99e94854646a9f288c1e851dfac6d88461495982859b2f49f137b965bea44f1faea3ac601f1b3587f205c50b6a9a5622a35d2871cd381a2d2ca7de8d8080d1663f2450eefd4925a4aa2f63667d594d12d66cf601083c0652a7d6134b9b3fda3cfc79011143413409683591a9d19bd87fdd6d5160c1136773c7a798f04bc9b0814672a9766fd00d7fe8d79fb47b395ecb6e13a69332de29e2875b245b8a2e7aff392658a8aa7d6a6af70718000b073c6fad923a20625476e63a58af47cd72f5962e00755ce4d115849c1123d25f314b80afeb912e948f4eca3db79b886d8aa200d0a1abe2dc0094033ae2c9297bb36bbe1dbdb26bc8c409487ababadf59ba507dd4f38bc86b73bafaff534411636a2ebc86205d7912089da736381cadaae995f70ccd526fc36dc1267facc0c7707d7c3d723ca5ceffe3859f5a0d5e245fbfe39694798c66d3a84a1450f779bc09a96cae66366f9ae6669587b6266cd7acb28a98e4d4aad0ffa854f8084bf6d614e195df5a0a194a389bc1b90e2572f3285a82509d149e08ae5711242f138661f91ba6f19a1ffd362c31f481519d55c6044991587606ccfd0af42574ba4f32ba317d71b540a10fce1d9f780203d5d2293a5fb630d3d3c3fc969bc13ea08d2ccadf26c2353c60d4af9a0dc5ce876f38ab56472d54c27dca61f1ebd271b725b05e2cfc965c8d1bf8d9aa600f75e2ed7de7c4b65bbca07dab6ba94dc0036876b6af826e5dd097c2a7885e3da98629d7d45780bdb92d7afb21f38690779de408e498a73bb7e56119ce786fc8a2771199ee5f10d4e07c2e7f27774338da8257d9a35467ae9390ee22e9b796e6093ad18ad4e5c22208021019d5c637516c050333c60deb46e2fb56d59b1f77ad4cc2846214d06e50962e97aceedeae0fa8c3fb51675f2d590382f9778c177201e8b058e4511d67768d27b5e05de19e7485d6fe7a6ffbc034bd8a759507e47bbe74b1eb1c04db0bb3dc781912f03f26d99b692145d83eb62185e0404c998cf3370ed09c3f2b75efe1bcc4001fc2a90e7888e052ce151612da87191685e4d25ef790b742e30419a8f239b8ed4a0bcf8d11cf3e9a301790609a7a428f96581c1070f78294d8aeb1ea05ea49f80a8e08105f114e1d5a1fbab9f4faf4c209e52d1910d471919ed77a34e4113322f1843ecb1148b77cda8fdcc0176fd28eea16f5a785371ebb2456df0dabf9c5962cbecbc26df5c6509c295e568ca6210303cd8b07fffa6fe2b5da021d592d18f03ac019f0e17426177115a52381958c3b90419fb9b25fcd5b5077b2ddde256bb4178fb4a864616c2b80fe3ccbd3848808678f19ccf6161aaa1e761d6f8ccc90e720318d2983198701e7a130c0c6c9199cc03f103b2ce97ec6ba28b9c68fb8df31314880e09689e93d90a57cbcc12cfb718f7352b6d328490a837134124c047d62526b9774530eefe8d926d7559469c2e84a5cd846d837b0474e8929ad586dcd756b5ff355994a8da2e65bfb0f60a664f210d66691aeb6302e62c3ace32662fc5c9eb68a591735ab1814358b5c2edef8bb5790cd88443aa0ab94aa0ad0ddb709bf815b17d532be68f678ea395a8721e853e546293dff2b543df6aab1bc987f5b3bde6ade0f9bdcbc85d6086220b89a402a67ad8f923fcdb2b2fcacd0e3bdf8d0d9c8cc4ca659910012bca46ff18b20ba61a0501d7d3d775a70b2e0f7fc139f5285b230c351dbf2696f2df1bd94749de3cf597a5039eaeb592d57db18c5948f73e912476730ce05cf8bfab523cfcf6681bbdec9dc72ab2e590dcbf932e0734ee82721b188ddc6f284e828ca7002b7c57783881cbfe1b63eaebc5eb8dd6777e10226a65f1564844c819966ac9ebcb0e52b8a8aecf2b8161b953846e1f0760b4adb0b2f40e6fa6236e3a54363afbdbe1f66959773421c9390f75baafab9f88ef2d7331e061e0d367d2e8c905ae421bcb49ce64537e5712e7bc1df91675d4af752346fa1a2478fec14981792c827beb0f0305a3b9025e1d7a4ea51561cd91be3779c0ec8dc104cf12d78baf543422c21a830eddbd624a140a4af44ba48e71ee04fab2f586022371783001a77cabbf365aa22e755337225961d53a299dd5ba94f73d678b615625ad76584d69fe3f9922508394aca96d3b1c91fd9836c68b3db7e5748795889320fa99e353213238ff900e027f1938d680599ec13cf932f4a0916480b48e9c51c0b3472787f9da3ec86d3ed61534147210caacccf2b66e6cb9265d42656a9812ac2e1524ca109b63de4a969fbd8d5c4f76b9bbf65c4ce9bdd398a49d0e0d8f30e0a34dbfae75bd3421dcadd61187e0ba2e3a68999727080419e95e9ba1c1cffa9746f001082df6ec40c950560780da3192799948f85326b10735a71fc47b4fce70afd9713ebdb65ea1ba1baad73eca13ef064cb866e1915b4ec6e499d6fcf888d09211d796cb4ef4c21dbc3f959a633f24210576b265ebf79833faa26b5fe43c036e4eefd71963d2e2ed1c9e9980a60b2b3adf409cad753fd4df82d0cb71852ca9845c7e2ce5a4cc6115a9d1957ef352f659fe7c878fe6303817edcedf050d6d2e6066be538e7d0864d82c901d1621b41310243e4d3ab67a8e0062acb0344c6e69dc561d542f530123ac3889308822fac67ebef8c11a5733598dabc1bf9d22efd6146d1ba403b45b2a6295ca68af3952e9e6ea73f49d630048c1ab852481b0cc0a6fe509e15c0ffa471f385eab23701485630d92b921bde3242f1517dce2135465a6f9afef7eadc9326468bc24a474dca9516aa67ff1609bcf50da494ab9b0151115497cc035e7ec81aa9815a4c4507de30ff4822987adec900b15c69bc3b217210094a10582d6bf45de8a82bcfd2ec3515c612993f9f971bf9018ac3d052f576893fde516ed2f573f146c5d2204a4d51f6bc19a7a0deb93586a8cc249bc94ad937104ac1521fa457a6028171ed3029adf6148c932d1160ee3549ee34970d50c1a660fb9d13abe78a2b4008d1ec45f53999fa82c9501e823cb0ed33667822059d844f581bf1a5037ea3b514d932cc3ec74d871c66df7a53fc388db6717fa16de2d34c89977de5d14953c10eb312a07c09f98a9bcf07cbc97f32bd342a650adabb1f2c20b01a96a6f730a3902647d9fda289f08d4f41182a69c1ca7a716050f72a9640afbfec5ad3ee46bf2e6702060aa2b49ad460bf178aeea5f1b920790f12871f0fb42ec6d8a1733850ee7b32996dbafebc841122dc0aa071fab7ba2a142ea15cdf10731988d919cfbb38de3df5cee47302f7bc0b178284b9fd9aea4c631184a8ad5a95b653095524b5e06cfa5d8dce93867dbc00be6c0984b50c4c3d706684ad40c0ad089b1e49be35afe3ee7db9d14f670ef65f43c7c20f2c5488048d0155046dba2a54de242cabffaa0552a6bada87d3e0388c39d22cbd172ca93e2a78439d1115bb42600566bf54891ab43d5e7e2d507f489f95cfbbcadfb40b17aa26aba3a68cdb3b4fc4560c976996993ab7e10022e9dc3a14f0226c6cd22531ce910cbccfdbd46a49271d6dc5d6db21ebc247a8d75a28e3a4a1f07d87947933e44c80495f23304fd6550df24157d81ae2cb738661beff55fa171c9a9386df917052e9b6728e8ca3dfedbed30c72fb35d44c35e53fc45e9446e7d55e360aacc70fc8a476470aecf98dfefbb67f1dee6c441a9845139c374249d8514c49761a255bbba7735944c5d9c4eadf9590000e1cf32da0d7c8c317c0af21ac1000d4f65c83ec5d6fa163887d1a9de7eda306f38d4bf65144c6a762aeb0e3a40d5c21c0cde6f4e84cf8aac707088567001398476201a40435f6223c6c3ceeee950710be84524dbedc1d166b0df5114f6a8ee92c13a141cb2cf57deeaecc0f15dd0e047e430fdbe0093c55dc6e170cef80ad02e2b05d59342dbf0559c5d4db59dbc11596092fd254d88f7f0d6e61bd1d6551d9c00fe46378efe8287f3ad628b7c625ec465ef774e64cb6d7b31c58ef7de2ab1f8541082ddd1e3693dfee380d6dd4bb36f849e20b2cc7096ecb59170210053126ce8f7ec65124329a26c56fee29592c22efe421e2bbcc9df7ace04aa73ffdd92a0a01dfc019cfeea7bb7805cb5558c2b08318368b3bba14c39bffe86ff78a780d24accd38d6daa30cc6311cd8aefd80a6072fc47213fc2874899fea1fbc74b9f8a9b1409bfe38ce15e48883d8b0829399417ef56224493ed16ecfcbc4acbe2dd8ee5ad1d9f543f919a1c4c538ab63b1e3fa58e2e98bb0fed81cd829410d423d5b7e509fbe5ca3da14803ece9a0d66368bb8f3f2f20f2c7413f66c5122a9383f546fda84c06d988d6f96374fd1d05f82bd317e5e2a6c9e17d37182550738d098e0ef01b848f51f70e56c926cb1e5fbca61f0ee5fe4b78c4ca88420f9d94c01082e12e447d80673b791596dd99d270e66c6a24f346e7a3993fbfcafbf8b0e15b29a36a114462868dcf89fba1bc1ea9c69f85d8d4ca170f809dc4f7cfd1d301e32b5fb97423c338472ce5236bbc27e353b97a6b24b6cc9949d21c0d0bb2ad428d9e1340d9c930a3d5c259d7d8b2b4c002c070412edb3e8b17e47ec4450ee006b1c3a80899559990171072d8eb074b6c0874847d30bb6305b2f1be70f23ae379cfb27d41985de327b2fdd95804ff614f995d5b36ac3c825cb3002c502c93d986e37595bc3eee85dc24e3209d47c7a6956981ff1d3493a885bfdc2d2822264f2e6a0a675aa5057dc66d32b2952026034ac7dbf45dc016c837b50dbe736a3a96bc85fc6137aecf04d5d4fdec34020e709c64dde56385a1d73930573865f2a1099aa9edd702db67f2d47b1f657246c9cad024812551af9d6ad7b51b0c8d5c2b7e1ec376cfda50070801979b68ab18b5f91043badc00cc8e3428f06a74118e80709f905ee57fc3b3b5e1b757764f9ed52d83ce102f45212417cd06379b6b6d153223e1358c473bc91e1b6496c59bda57b872e0ed913433ae195582c2d2e0b9bc8b1e95ef39367787e4ff4d8c2bee75d433087b39bea202fe127e4ffabbf0941e1bf8d4cf6985717fb5f2bf2e40254e45202b05a2d333a9e5d81b63bfdfa70aca759d76d539121343418cb977dbb2d6ab66e292784161f6b7c028717e8651d05631bdfe4465400d6c406d84643383602c23c4fa172939fe0d9e9c71eaf47417b1c1d4ee2edd10c2ac92097260ef2f5be004a654993e53b3ed407beb1559a5b46e1feec1c07b52b6ac51921e0aa8adbba164009b2f7d4de557394865906bac2e022b438115288474e43e845874bbb35db0c767aa172be1d1eff98197989734f3a7bebf412457f0a835cbd91f32ff73485cb7c8bdb47f6e7815f1899a80fc4ab85033b57cac5e62db3abcc4745458a40e31210bad69d643fac7136bf82f22b5bce998f43ab76d0e48c4bd0300f01808c59f1b8572f4f617154e98fe53ceddd055c5a69cf40d73d1e5fc55b6d6a6765f7c73ff6420ccf394ebb923e3b2cc9e455074be840ef117200dfa10fc1fbc20c10c1d6a0b1c1a981d2aed1d817555389788c9d85b5e116e2570fbd1eda858aaa5ecd075d0c0f1135b6ae66f05f32fec92b7d7f4fbf6416f5af792882217f297a5dba7b1f0d3a43c9d71d82cc5c2818adc065ae4d8928870e4c6540e671d5b00236a1f252aaaaae3583f0ee1d7476fc433b1fb62a35c9aefb0d61e964c83d452e67a630e6384b8f5ecdd1dcdfabf1913d0a246e902d206cb73a3d72aef9f12b07b8b3098991579f1d7aa936430abec920d57d2fe2e6ba517ceb837ac2ca397075aa236035dcdf10df948d5f90bde577ee6e5049ebd56ad8fadb366b1b1f1a577a0faa5d437fd5f8c2cee5baafe7a26727dfa9da89dd29e2cbcf2770a3dc07326cdeeaa9cbaf975b8c2a27727061bdc966eb48fbd81a045adc15804ef6891cf6d0669228dc3e629a977e447ad4947ae7df574dc59d11314e75c43a574bb69a7a0a5d5a66e24cd79f37d3d6cc94f20a57b5d887e5ffadb04131157e4f3ce8314e96c95ae82c15698e6fabb4436c68dbcba79132b346f13eb671702846cdd1f4e7366e16ed7ad9e2433c9b6b6f1aaa4056ab0cf4b93c7624a2ecfd73d602a73edd8d52a7ea405833bbd7157bcbdfab935e2faad4b7ad905b64d209e332d4abdb46c07af8777d3426aac546c0310a1c6c9a4ae4b9f73a5489ffbc58e85187d812044344412b4e4ace498c698c466aa97530ef8e60c7b40a4e018e9889eb73c84666be377fb8f361b25f16cc5fe23a30ff648257bd579dda8b7410a9ffc0012aec0563e85108a6c2d75e94b24be4a0db3572c791e1a8d920b4ab498ee646395b29fa438d67d0cd30736b8a99c98b00c6e4cc3660df5a109ef81b8fd8927b6d94d5e20ca9343037a0ef710797d2cb9a1a3f2bb3e807882f5ff1519f479d46ab9ad10d51b887c4ea9ca01f044fd96e5fc7fffd8b60a4b55df9e4828b26777f9c9618a956141ff9dbf315477f910cef5d7b7abe412707dc312377dbda4756a7d3b96a0630b7cb4f8ede5cb1ed64c8c55e5f2edec57a1f3a357949bfce3977c44d7ce442626bf8c2397c720c1d5397ab618439fdec114b4a66b22e110809c764eeecd39b11a2af391e54d22124db1666b529f0efbabe36b4db33719bef17a541fb61b5c4bda5843a49a92c356bae996eb95861b75f126bd7283e5c2d8f7761db2953dd4962d843ddc1334ee29bc5a9153c3f0ab500610bab47b731feffe2744a5001cf7e540e2256a2a957a05c916b1bf9c317549ab5aeea60d7e4a7e3b9892900f6df42af7d81d7aabf185aa6040a0e69a22ba822f1e0afc2cab9a0b7336ff68c2ea332e8bad932f1fbf033eb6157ff8d26ebe3750d4c060d8a7c4336ef3ae1fd733072452f52c4079f25bb0e6b8dc9e4e99e37485af08058db93fa1d8929a8d986bcbf9b3b9e5ad8bdefdf4e6ae84c705bd0413096808138b7f61cd8e474d3303ab134611ad4a3566a334a8f73f760a38fdf485e77cb063f1038d5b1a0ab5535a700c4b30fb378adb5abf17c0c834a0bae1db5874dd353902508d879f8999b7cab51043d1d6ab4a89e1a92052e9e9079441965a41cf9543e884721d65a73e488f4c91a5971cfa8d22dce4dd4a1f28097c6750de779eb2d7d3f9504660cf55b99cad11a3cbf7c5b2af7aab11be52943111034c849074daff85a48a756ca443ca389a319784b803ed10f4fabb60dd0b0add2a1079055a48cf634a73a13f558518ad7125e9959aeaa0ac5f394ea9df9f4c0fc2d5c474bd5388e618cb5196fdb37350e7906a6076d58be9257f5c9381a95265e7edf73be144880d6ea338257ffdfbaa77f6b8579321d3e0f612d51731474685bdda5faa00f450975ae8c0e8bc4c72bee112ff53af62856d96f7427b2178cedfe4bc4152bb04e99079df0fedf6c1a9c077df47c027cb5e04766ff708bb8a558a3c8bbef618497c1b0d55a0739e78ed189bf62cc24d91d25904a82070bf55954cae7712fce9e7e4f1043a02642b2966fc6c7e5df3ee172187f5783b1b71fdda00f707fff529a4217cc3a4b247997e30cf198279c01bb7639e75b96cb5972b034b8afa6697af9ba347423b96fec4906b70b4fbfd7c8ea5e508bfcf28f4b18130d329c59488e21a7e41f7db7f77846fb16adbce282b13bd0a5d09a272cf8d7eac7a7eceaf4cde65be196cec531b4a1585efc6cd3c07a93341dfc623e847b640b612a137d6175df0762a770106dcd707a31d610c6a8b8fc92bd1aaf32ab313abf8965a6c7c08d350730d8da969bd3a2c882abc43ecf6562b571aa24d908263b87a35d17d740fa357e34086cd1a2e03ef6361f15621774128c04e2e5b41385aa528e7c62774163ba30bfe33958456947a6dbdd38e8dcf579bd4a6a9bfcc539a1dd2d83531d887e4e8c2eb54fcbbb3eed19756e1803e97a9c9d91b556f84320414ca1d64693256bb42a45f474c9fc5ed0198d3c22e98fad195d50d716b6211da44f9400c06a03a3c4895e5f4c1fab268d403fc02bbbc14a0da0956b777bd77624d8f6031d5e062d58e06fedfcb878db48159c5852de0aa6c1b080ff625c4ef3931e169e3b4991598186084b48946d8b27991c24db92a23e02fd3926dc85e16151eae41e0f134705cb6d44890a1f67acfcf609134291915cf7c2f3c21a474d83db581bacdc440e01ea70077b441342d85e2fd94b352a5be8469ac80d7d7e0ea62703580821bbc6d0bcb95787efb10f63d496bcc529c102f7645b7961647d06e882bb1c90197d67c4bb56387c4b8730bbe3416e32611c08b11594347bd6fca6ebe2d3d8e706291c1e8ba72f2ea5799230e1dc7211bf66518e7fc95678006729dd2f32cbe4ae7346360e9051483236c1911c9188c187e5dbf00560810bfa60f027639d189c73c970c78a7dcfe7e2670c21841b772ed6343efc143c26233e3d829cbea88c6d04f653fd60575012d22535c20e1f8b2ef7ab3189c88019e7739726b22351bdb01c665299fa5462f80d74bbdf394f80b8e93dd9f07d5d0541e829aa98561fba7d576627913ce62c77ad07a36dae6b75de75744f465633e1f3d8b43a03bada249dc2e0686f3da6d2f6675e8867d763a20d7bb1129daa46f4970751e5d82be2cb5bb43b727b179e26d930d11e052fa3d45911dd3bca0ff37e2ebc1e8e8c0565a8de9ef4a0bc043c41605c761ba8df4dcc059f2d958bc8688b6ef3ae1f274c9aad2270769f7a7001aaf4bb30a0666e9874ec0f703bf9e41047702e9aae32c3c666187d124447609d1cf0a73269d1e20e63b6d49d4978016e181aa7cc0dfe7204f2fd3318c80358161e3a3c7b54abd4b2efe88d2b9afa25dbeea800daaff60bebf38fdb03577ef2931b879d02dc26886af4b7c64edad7e514b539b20d1c94fe58fee7a1445062aefcbafba08a426ce2d643150eeef5a7b511319eb27a78a48e44e9b0f73ce74e166abbd3bc681276a5ae6b4b6366c941b99630a16f30ca5ea56e67aabcc1c5f6557375e6c87e4bfb0fdc19d37d48b9376051518ab091356262524427af3aa38c3fba028fc49c72661b8136633295098e69631278f4bade03e24c127b41dafac816cbc730ed709ecf70afcce75be243ead25d07ef6087c1ebe9157e39444f7503dff083491ee598932d404f16c91709d27d881b5c8a5e77c15f522db424bbdac1bef454f09a56a3ae0b7c472fe7ab52737db937619e5249fa4bd11a53b4a8f18b76d930b8a41ca15018a217b36d9a544f821a1bdd28c1bbd817e2581726aef4568bc5f27e14ce4a01fde67eb887254b2114bec2734e26f4c414f0643f62f344377713bc7d602a7237c5633d431c8e81e3f9896fac40c74a9e119c13fcbc8150dc0409c413b7a53dc2accc555799e1723bbc348496acb815277acc812075bd1270979274009df00264c3af85d430d2ca9d1929d6e7198de0232b68f576f913005291acd31d24750320f8d0ca496074f51afe3e2ea669d155b9e7564e4c811d1f977c50bb116ad733288b07309e91f1fc5cfb53ca32abedcaa48af510ceeaebb4c775e4136d4318ef109a39efd7a1ccf56178e8e20fa3f9ee4a903134836c5dc2ef3d50b6aa9944da3b45a51b353817c7d55d6f6d0491f559522f0ac904e8468a995c23252c3ebb4063c8d8a6b2834aa6749f61201d6434aab80b2dfec3561702161b95d9ac931095b8e454e97cebd68ead802634e499f90e249ff0e42c1bc160f3e739cd73a4828e73196034c6065b7311190697d0585dbcc65fe484296acf7d7586e20e8f27fbb10af9b33624064deae686f937d1bb1c70cccfb7b15b41764de253e22ef5023eef168f2f6ec24b261c98b8d741699fbd963579254f5d1ce649129e6343c02756fe39d46896ebd0f89a3d4e3bfed03f273c4455275929d538e4dd2d46fcc26954c0943f4c22bb9949fcbcac0bc349d66f5b7e469b7836f80f743318f9a96997075b7d67991fb9b0a2ffa40de6441e4d81c13f7014f7f4d1cf818b99ea4b60a34c25944e12538f6b388a1eea29196dcce410743ea438f18753d47efaebd054057560cff855e3ce60d4a0c7bb1b0d6f93c9e573310a20fd9e6081862362d79f113ccc219c861a17c02b902b18733a5fa98b6f2b9fd30051b0e7541100c25089d83d573c8c144785d95472a525db52a50d4c84e1df4c7706b013211a6b51ba47649385994f88db4554984b3b6db1710270f346ec39baa4e78828553bab99fb008c03e2919e41c705e18287ea00dc13cc6318cf6ba0c9c7b95410a85f69c4d8a753e020f9d2b08843fcbad388766fb7fe72af63b2a1e3eca0c22db1f088d44635857da001ab193fa9e3f89d50197c49ff3bb349e9b5049bd968fd14b28af85973ba01ec9c054d544cfb42f801c12cf840f969666da720d33c48adab406956c986c7bb3dc65ec44cb00deb1ca8af2f2b4de4488f8e54278d35bc0b71d7faf9455f48b4e4960fc5b928244277c5b2a854ad39da77fcfe38f1f5a382f64ca2b46e30ccbb78c341e60792e1e5a873c461641eb4fc3b3b0787066085da0bcb6553f9f8ee061d46e9f969c79bd0ea199794a5874b48016caf70f9fb87863d5aad09e0cb3951c699ee67beb2c64464aaa026897a99c793c418b4a2709f99818b07ba562daa19bb34dc26c2a1abcee078616156ed651ca09e79dac7ca8e47b39aae05a51719267cde46768a0d50510bdcc6e22e5c28aac62f83d172187b068dca935f96c5ad90325de8aa60813f186440e228d6c858f09274eac3ffc2793432b57131d7470e0972dbd450a246b33d7bd49cb756c3e447b0935a3b4a4c56bda644737b08712377c285b41ed57119d59cd7b58fa8fffd37c172ce9c0fb6a4c3f81dc3de251da3eccf3c6d79e334ede0ffbef3be83a49cdaccb5e4415bfb27fd647302747e8b56bebe4ce178c7c302126b75920e9a605bc57a4c796ce1c146807e1149680f9a9fb9cdce171d49ea83aae50409462f47dbdc6da45a5ba098b32d1d0dc2494864616e78cd2e6aa4a00b179280d0248a23bce105673eb9854459cdae210cc6843ba4b2df98aa9146d703b51e3e0209076353ef89e684fbc444b674b263b11abb99df558d676717f943f66e9a6de1694de20bd91eaf850fb2411a869e40963f15b4d17341846b1bcef47cff8507aa8e7d60d195e30562fc6144d750586b18bddab81645cf2be2e8dad1118fa6537909a55aa9f4d7719e45b99940f40251a1afdccff5f686889dce5af32333359807da5ee0ad7a6af5f17280eb63fc42f0e7906965e0be91c0d3d72ecadd17772e609f1aa8cf59d2c392bea5825a7041410a743ca61d6924fdaadaf8d5fc56f1d2283668c059aa4717081e1c2d4e842269a53c712cfb73dae33dfaea9a559e3b76aba0c9e30de60539d0a1b3729166b2315c485058deb9bc9a36f91dbe50cce6b6a1c0853f91f8ccf86ac77f577245b45096a8ff2d2dd4a8bafc9aa64885b44ed012e009fdf5502c947db55829f9ebbedb4059da62fc2f54a91adf051ebf41fc4802bec09a9c6aa5a586627e13c3718b4f8890b1dc458afff6ba05b072af3e14d791ab00935ce0da995dee167d651c363ce6d16f0baf3841e82163f8a88f66240789100008b8d32f46d226a2affb457b8813b152b2b46e16e98b02c4bb9bfff36ba6e789201d93a9b4f75f4f35a63d75aca4a9e8ede90e8668add453812d2649a5cb6578f2aaffd97ec35ec7425e08e1484647aa8e426136c0af9f4f033441c7e2d684ca3346d6f024503b99eaa2a35ad446b9067c15c2fad75388efa6c2846e13509c3483fc5569c5ab5fa27cc1b3f3e58c256a2026442657bd79610f329a40eec1640e2e3dcb6989bbd7780782e803527ddab67d1bb2d09a91a6425ddfbf71cf01121bb447b91b12aee1d5ee509b1b36b1173930f4d4c1ec5cb13d1369871e4b4be447ac21565a0456dfdeeb921b3b7b1280e3e08b53054d9f64ee065a345548014555d4ca4c2605fb2a1f2363d132947473ce32200f2eae3bffdc209729c664d08b73ed4f6c5587a4914001582030c687a23f35035c3a4370f0d84c8bb97a5ef771b3fd4a19a00bddc053fa13b9c3440255c0cf16499640d31ce77e18003a08e567010ac493859fd06f499d66b8dfaefbc6423e05cc7f6239c1ebd533820cf08fcfbbcbf53581a92bd838331e3f8cd03ac8d43919cba88efb8ca0443379cf4fb29a5d366c9c7e837a847424cf8dd5cefff2b317b2a155d00437d9179b73ecedb012968dfffd737e5e3812548e8e1e6a26b0424beb2eaeae325ecf747a27e93ec240f3e7cece64250787bf6e4cbae6ed2e9fb7b91728b07e90e21248c73224e509d8b7c7fa43bed59d0e03d3b791417e7f82e234f654eb865fdb086a522d2d12389f64c074cdfac42b4aa73ba70f1451c14462edf79ddc66c3f2a4d7b4852b2d2d0c70ba1e3c0b3a7c7710462c8401451b55209e4d38a103cac69e3d88457996aa6f574c28331b737677b27a161eee647140ce7da0913b44d827bf59ab4bd4034bb9ae3f799a73de885cd73b9efa56f6231ff52707d7fc640809bae3c04b1b650eaa15669962351f431de86fd5ad46c4d50639c444c63a8d0f6b3b7329df38df0261b11e200dafbfbdb171e84be5a588ddcb75d1c518647a243e518a38d0ad1ab5bc7119e0c5865332b6b0ad0922dd8da75f33a29504090053dc71d2be78dd571286f805c257dfbfd87d77dd188533323560a11e351f9792ee7cfaf44889942c4cb4ce19610d1c1f2be7233568627f0a6593bbe5038d790c62ffc89c995eff39862fdae75906696d38bca02bce255fe2ee1eaff9d0e0cf14f6d22f7138965f4240073b5aae454fb98c9299de92a66036b25926aa0d433e95f24e7fd84190185da409b1ad15f42461a0eb0d18769179a633ffa19ad0cf6e7b6988ad7c1d49147ed67c242a50ed017be10211fca66331b3ee9a0f04c0eff67da67962e17feb072ddb9c90bb1a33e4449b959077d438fad6eb2dcddbb12c228bb0e9bef543d05e9bd012e6ed12ca7df44fae9fb175603e51f38735433a3c4de6b0d618f970a2d6ca7566bf70f38b9f400fe93179182ed2901239f8bd2786aa07e2bb5b9785ce62e70b011c58266094ae62134d6174c15be8fc885268de22ab16ff518d404b88adbacfa91eb626fcf6d166a0ee3e2301d624739db96c80308f50f3f720024c9e6841d7187b283d369c26df5aa31f286ff480dbf9d5e6f6028c5c605c88f99ab358e88255c9e922f97983460d72279ac8b26ebe13b84002ed31e0bfd0e8e919d9144a7cf9306d7bea447367d3553f91e8a2a1b8aeee7954b3fa0a602ede90e6463e8fc14eb4706b5b6add633f4afb1f3d82e3b6f52f578165a9e2745a9e6a6f0615ef16601b8e09935c398a092fdd6cf04b16af810e0849b233b77a08bba219ec76bc6ef14b609805dbad2b099a6008783a83f40830bcaa9264847168e33f419abf89318976d961c108e4b205971597b5c3828c237de80f5152063c4ca16f333957953e25f1239d931aed28774c31596293232a230c126ee00c830278a4a8d7c293fbda10f8ff570ea18cecdaccb67541371402d9016d212c44a97e5cbb6ad2fef200a72f4c590f0b73a9046d460f0c26f2334ee57cca825392d87ab412f79857a293b6f76e7b6ca80aaf0d933960cfbd778354682b34212c0a069f70d34b7e401affe48955735eb5244e21e1c3cffb424b6954283c71c57903c1ebdd21491294c97604c3334b44b2da3c2d2956a959368b2f2b0ca77766d1806cfa3fd21fd459e069212e06947af63df02eb99248a516d646cc8a2f99a77cb73eda7286bce1101c4be3009b7420c6fde2aceaa059dbf6963e541e74ba22f18a9de0eb14f1339f6648dd5198e43843f78695daa45b4e84ba08653e1d7aabcab22aaf06c99b447d3757a6cbbc7b7ce90e075e143ce4884a8ddce70cbfa612c8ae47f5e03e954d275c704c5dde1bdf5dd32151b4eed6417e1d0c2f934637aa172f19abe2ed1d74604b62644f37bd83f42cc2392e3c25f54cd3a84f5e382a6676109a3feef309300ee4e49c42234835f3d1990077d1f06c243589bb13fe453e9da346fe54bb24ecb26dc48d97dc468311d7df38f873c425ea7ccb55ef9393fd001673cd3702356169ba915f6a08894c86eccbde5d1e772958b89f54b2ac0a1d3fa20d2df7c3a6f4a22f730724a65143065771113b1fd630d03ed312a16ae1421b472be08cceb8bd582c2852a4fc0f4b18c3db32b080ae2fc2b4ff70c28360fc40372bff7daadf74e748a023a7889aa038fbe2d215af08b2f8e066305c22401cbbc2bf02463e1fe73c4a60c825222f0c153333833ff4b78c08bee8bb0ae2957631ba83fd579f2b6478f850f7466b50e38a33d76472a806ada0db6bd4cacf292dd55a22e7da2ea85fdeeb906e81b609972bf414d015fdaab90bc1bd7e7eaec256d1ed117e3390ccdc682354272c5b867437dc2fef4d77978fe6ec857b5314d704c750dd61345f90650ebc3a9d9da86ed2b608e19804b18995e5261b200a5e56c1ccbc0a0fd2a037fe34e3a6b70792364bcbe7de98297e2a8386939dbff8aba0a2b1d7ae7fd78fe0d275e7c893282df908b9a929770d288b66019ae2921a417d33db78f23f5d11911052967d621129fafb307ba906dea6dc67547a0f5cc9f6d751dee9aa1af6f865eb1efed4266ec0e16fdfc13290bf2e03f4fa8bffbb1b85a1d38c5a60319c3d99f2afa56e148a7fb9fe7546ee6d73f52e663a7fd17349ea653c8bce7bf424a7bc7ce59868c7e8a53fa4b8c75c494ed396afdf64a801edbd24b065e61a0e881798824b9eac67079c07b04ce8dec2b70f928be0bd16fd742391a40eb19e3c88f6c3e51b28be2a336be33246c4e75cfd78f4c53cd596dfb84dc9c7be0e08cfb1822ba5dbaadeddace7dc15e4eb73497c8c5695afd801830d390d97b2891a434227c53527f6daa0a10a8856b5fd22bedfc32c5e61084879b69dc9563aa2b1b3c6a44651a7968072e1cd3368d175c46c6f063dc3932a85db0d8d7ca71c27230b0733c5ed96a1d4f73759d8928e549231bc0d013ffc64ace2048763dfa11a2514e5e66652eb06ee9500f92bfcfc471c2156ddae987936f2a59d743e117bdb9b7f72fad257403b8f19cb5406c7305579ecb3b6a530553275448cde7cd097a189dcf10745295cef5b43b70ab16263ef4b368d93861bc9fb536b3221b57a0acc4725f1772fe55f58477ef846c243536e437b6bcfafaabbb9edc1869670d442b8bd1d57ea6d9a4a85578606d99a2b4275631fdff1e63b0a2c21b7f210b0077c96627d0012171a1083e1b38ed6f6405f07f4dcecc34a56374677dc18a4420a277f6b96eb3571831dff053975221ca514f0803a588db5d2222a536d35c50dbf404c416f4ebbf8c7e08d366d1839e0c528b1f77ce4a8c4a61eeefd7a22c911f694a863962b2de8e502853a6b779110ed7ccc225e50270bd1c159b23628802bce3d2be63a13a3a29f88ac7f8e42823eda6d52f93678ccc4e893b7ed56eb31971d09d69e454356d473b523b3b8f09cf916acfbad1e22c65c3daf86741d421e06de0d20b6711c847fc18c6537a4b50f67f9f775cc840c9eeb5e6393da9f52977d2b3bd741e3323c430cbfc05d897ca01f4bc9b4091de1469c7bdd3f22a1d70f3c7202e7944110513fe191aa5fd0e4f48ebf932c928184839a0420b293dee18ae9f4f843fa92af8c2a7895e77bb5ef7ee694018563e5f4db97147c3da672124d455ad9d3d4a7f0cb4c37ea48b9dc055712d1fe978a60cd8bf32f6297ffc365be7e7db61f82fe2b4cfc051db926efae456a8e5fd07cc4b87f6461ccf7089a7e168c5965c9cdfeb50fbe757009e35a58d508531b3c78f1a014b10d07965243c09cedcdcd74554d3f9ca794a6e796919bfe65282dc27ce63f8fafa48620d2680363544a5376afaac3050b0caec01278c97ac481aea8f80845c4509005decd453ef7cac222674445d0ef7f4198c51df98782cf00d59cd2d963c184d0115eeb8c0a2c0e62c8de1e9e4c5e25a86435154a46d5cc1746eca063d07e2c1c97268e8ae99106f9bd2a00276640854d4f4484781feaa30117f063add76943f35fc86f26af4ed6ace790b37ff5f078e98c7b67835af300001b521be7156fce055bc1930f4a17561de2af09b167f414146849318625b27fe803584c4df3dcf47b28e590e6ffae59f1758c53ab4cdc57d738af933525ae0aae83a806363aa0466c0e71280bd36c1bbc9f3437587cc24522f583b52e7b220c2f331a019a9361e67bebdf10f78377d1264cd97fce20c9e42ee60cd5103f8e5911a667b06087ad269040cc3f0d40e7b07befc41d7cef318a7f7e78e4406e0fb06175c77c07d8b7292e649813a0ea9740181f509985022b5b6a3cff7dd5c6e5b388346150bd024435bd4487857ec84d3fd848e0f364b2bb9af80bbf4980373f724ae0604517e945d687b099c50890b14bc409b4f453625dc674a66fc9a1ee455d465b2f1d00d77b7b4d349acc930761c085c86feda1e696c2758c1bc8be3a4ad4b96a8161378410dad8add479b20aa53dc0824f19085e446f48a6628c6502ee6c1d8344f292f860b69494d6b91951fa589dba346dd863ba11e2d243083cfadd76c27e78c86dfc35b42eba41b43e9ea7ad995f4b41f3ec99e10126e40df13f016382bd4cab5ee046de5386de49829349a7aaff0fb1016b3c8a11b0f6d1a3382219d959e5ef9618717f5f96069b494bb014b0b26e06f364f24e152c9cfced5174d5e40b35dbcd00d395559f4ac4f543eaeef8afadc377f9c603860f0f363db24f37c33eecfb12f4a3d1ce9ee3d429cdc4372fc21cb1032c53b64135539487660d66bc96f0b00e249f97809d7da8b169d7660608c45171163e9a30ec903e34fee7aa5050072a88593c073d1da137d24666c14dc60e78ff98d42159357905fb3a9d762c45d365b624489c88f1bc2d1e96c0d931d887d684fad1e5c55993789a39c3e0c6734101fe3f621bcbb9d226397dc72baefddebbabf8ec3fdea90da625c0a3a28cb3bc0e68db06ad8fe457b793db1707437c979d73188134e6fcbd10efd1d96ba1360f5d89cf828cd55646fe5ee0d449ce625255ceb62589d6d60281d98f07758a5fa93f3813373b9dea4f2d8bf19ac14f1f8f4d4ec22a55842e49c4166acca9661fca9ffdb81c923ddcc9b39a124f6fcd26007d2a34c185944d639bafe41fbf5baf3ad0fb2bd1fa7f6851089610f965a961b0a97fb910d61d4d14d21c85747b1afeb303e7729c7b53172cfd98c2354d2a57718a585e9532bcd0b1f07463a7d3b43d805d294f36e6f8b265253e7d03b6888b2efefe388d9a971c48a994b8b25036c8bbfb61b1fc6d5e50fc11ef9c800b98e6b28d2aaa28c37632f58d40b7856c1766c48b38a6665af80578cc9bbd99e3f732d598c5805662242cd3127dd8a67edcb6e7d45348a461c532698d0b355c3fb75f654b4c681302db8b02973ec9086457e3240036d97ccdc3fde8beb611c559915c2461d7a0a3cc1ec169fc07468e208bfc50cf520032f54aa75bdf42b77a834bea777292b31062ee2086b2e3eea5a4c1ba458f25cc1a82abba610cd61136c289df62283c7a1309756a3d160a89e3161187d4da441880262a9a830a2d0cf8610831575250b1d9cef7b5c0f20f49667132213b209caded8951ea29edffd07801ae38f1df14b6a75b600bc12a472d15ca057f1de9a84dc69c13c58fc9317c3aefdf4ef7a515b209aa90808fd7e71ce6cb66be53acaa09410a9d34926ab9692179a59998e7d6280ecf33e5acfd3eaf7b9d30e25dda7858d4f024ab02a1f05a2fa37fa9a74b49a172111945b00f86a0fdabbd96b8251aa1f0a6ef22f2b1eee7e14cc697bb4d5ba2ae1f0d9a692cc5eb66ac3ce77d0fbd0fef3300275779a2d23739113bf73ff813898e085ea6d5d1f02ed84c929d89fbd4d64497da280043adf278662faba4c3e1e36270c82bcb426da6455c9ad2f4627a38b554a4dfdbc30b8951312e3ab11b0599b700cb7eac21509babaf00e0af37ff833a5a4cfd989cc192ea93213463cf9444d30e765e08759cbed38996c624bd9ee971ea601734ff7dc5f8afbd0236472b570beee1e4930b4d6a987fcfeb8464cf143db9756300a51531375f3511bad899786a102ae21cfc359ec669320441b782d3c96986af3ba3e05abe77ea46d3f98ef1577e82a00ec0a1c6ff59ae9d00c549a9911bee51d40c1aaffdaa0c80ada37e95eaf120b9a0b3f32eb89776611746dfcce924a8bc961de37fabc8aca629cb1beb364fb4e902ae463ddf6cf7a2d554d7a67e323e55d5534c3faec873f888589bb79d5822e91804800a893d796fe1595033f4b3c59d5072709b36f31a0297f9633f10dcf6247f7af02039930361a218031d9aec6cfbe42fe1785afcac4cce6cdd6c3dce9fe61c2eab0ac89bf099cfd6865788019cbe11b5eaa2004d45d2ea85febeea8858787cc849c2bd32df726379d5e91916c38d386e8f1d5e2386da4c34b37240970b9af09fba79c3b8723a2558327c54cfc972f945536f15ff4af6875d01e6fed16d80ae0f18681ab863b309a11e25c06c10b124b1bee5484098d12cfa2cf0392b1817f77e097d047df947a34e29ace116014cdba2ef0c1ba1dea16ed8d3478629b3be0fa348ddb37acea335f8627a8e9a834650cff5b2a82507d1dd686b54793e3aee32cbc847cc43ebcf45d4cecabf6e160a363cd76bcdfa7b271aa042dcc412bdc1f7a946cd53bfb27ac4b09c1df82ca3f71fa0e02668d4d746485d8c476ddbe100540d38b42709944d6722e7af432b5c0ad051091c8c3d4301ea027dec2550bc2c5e80e2bc19d16abf7e31f317dfb24d23f41786c49cb20479de394dfee526cf01c05eb78bbca27cc96c0514ea28cf2af8d4dca3977977c590bfb6adf60e377ab8be4c9eb435f92aab0c0e1eb912157dce5d699979d63e90cea1edc05c9104c64b8c2d38d41501bc5e1559591cc6a3aff60fdf3be078677a49dacc0f2662e6d00f076af3ee26a5bdbc26fa5dde0a2a8085ed0ea834af5bc74f4490939deb0de9d4ddee5344c14bc06a1a1e441cf26da20830e36b5426e1d65889c7aa5347d9d3f867a270306e34c24c2b6a5dcc8da4f94aaac294471e7b69df2ab61e7a52111aea6d83d7a4a8ed2f889732538c197b0fde4cfc38e6320a7c9ee7944a48de6a8474e5c706e4b665c83f2d2046703fc191752a783919a25b84eea8cbaed7e5b48c1f288bbdcf00a93cd95a2ff0b5fde942e8cddbf9ce776a4dd22b921e6c72766b58e6d105a3e357a15eda743c69eee38c62e93d2fff76704f9e215106ab4d1e202aa2e701a811efead8fe1fdbc56e3f2ef47795663ce022693475ca15d0bf58e28360ed51562da135ac7d68228e8f89ead00ca1a86467cb905361682511316a2f0410202c65cdc20bf82e9c2d5db0b70e62b34022021c380ea799b8bf95fadb7726f52d0da9cea94ea42ff7645ede40d2ef284c21bebd425f3f0924c4e463e9943778ca6ab774d159e2b84aed2820bf013e9e2d3d368b3534db0e21a1b4d03818ac61230d66083c9468ffaeb65b07063fabc0bdd7e994b9465d7b0fff46aa2f77fe7fa380a555958f34377d48d6c13a428167e01b8ae2c48001ebdc39aab3d2fab787e19daa840182c8457c5c8a6bac8809487ddba68cb3a1b505a167f294c6275a895d4d090b25a822ad54e49c5b5acaf52922eae59a7a9da7a27068b132a3a631ae29795931dfc25d04a73ee632322f795f89e3cc79a3b114ac38cd8b6bab47f518693c2fb6052dd9ff3fc51e161df85baac7d5365a19179600bf713d8db6269b54577a77422d281016710173153ded04ee2a0c659b1f609682b84a621a8c6b9d61ca531a269f15c4c84e617c8bf4a8605c635e5b7a818f72367b7cf0d538c569d99e00638ec4375b7d8ada5b466af370f1b05c0cf67ff1d06edb882713dd8d0cd88bbab0439ecdff2080e8390d2260c51cc665e5809939d39ea024b5f612a10661fb026c9bda3d7f94c34f92192da9d8fa7edf52eb505cf833d4cf2fd11b4b23a720b4a3cadffcdc8630add1cec4ac6e66c1ca4d9cc59400244067ab87145eb29ce3a0dfa267d975c7f203d012a451393e6654a216140bbcf4a3ceb8fa44c3d8994d288a09eaffa19b5503da477096b3c65a8f6258236b410c01f180385192a7a11ba76bc486ac22de592bfd5f78dc3b1c5d66e913f48111725576ce62de2da2fc8f81b4b98690697b5a9221455c9009d512ca257d7731b088667d588842a3d1e1ac4a8a076a212d77dfa62f50c61a27ca37d63f1905b4084813a8c1b34d92f39f717a77d722382165c80a970ecf6f18679f5e112271fa39961ab76ba990b4818515355d99191805afd3f02b3616d961ddd3c550e5930fa269e9c623e061c679e46337c984cda41fc021442b1a3244f21e0dd8b168f6b150b90130fdf1a341259f8b189eb8285340c77a5625a0f5dff0bbdcc610efaf7e9182c5af59e5a11a642ff83e3ecf508b2a48e1c6962f98afb2feb106100e8d3c86a06cb5df5b6b122defcb2f6cf604675e5e22e975b93acbbb761059067bb7163758cb54038deac4972fa0f7e68623cb63718a94acdcfef3de4dcef451ff497e31fc2e1308ca507d5e807af3f1d4338979ddc6e5186d7346cfd340ad604442cac3ab4b7138134b99bb0c4b05a90e3f041b976d2272500f3a59584c3ea272deceb85cbed12f86a345834d6afae970788b5cfe19ebf56a7ef27e0f236c6719e3241f446219e10810b6be260929bee35f19ab4da0c6cbc3c0492ad5b4000ad4c8d45b1191233c1b96dd969f0240b2fd3c4acef511fe71a7ca502f4a12966f2455d169052289fc9503e18b500ffc4b228820a60a556e8b27b001627e283d16e7cda9deaf6ca2126c03cfd8d26a4034bc4b91c09d4e125a9abecc5af2fcf357839054bb9f062c31fac4173b141df24366a086d3bf4f2a816261c6bee5405d465638f52056f8391c1582762aca6adbc4132cb4cb5ff681d525ea62d31f93eb89b4083bfeda6c9635d89195e13c72dff9093fd38dc39ea88505f05917cea2348f2694483761c93eaa05a3ef10c48417cb124a6ee9dc9006e5d4116f719648ccb856cbaec009fe54e3c596bff9944e9f357327beacbb85887cec103e6ec7d9ecf2fd0138678dc4f5b5be064e71db2b71e686f3423649f25244cc7a5e2512700ffbd3548a5ee073a148bd1c6bed649371acb81a57dea9d60c2e5a6b481ce43c6fb8d766f7a1f2b5bf8ff26c077856c924d91d1ffeabb07afba6c845dedac6d0f90766771d0a43ab11b8a62fe59826ecceb7ce393240cad01f8273fdb16ba9eb0a4850337f9398e1ad7bb02188792464e52b33b5c8b2d3542a951e98443b41878a9866323fedd51d79d72ed1efdbb5e66a2a62d3bc8ae510af44e23bc3890e8bef79c51decc3b23063f4e121b5cb59ba39a2559f910a206f9a28fd8117f14c4b3dbf252de35464dc3d92ad752a0de7820c5a79836e9af093105724066d05a18a4ee80191651a19c3a74e571f364c41b977dd8fccb050c1333d3ab1869a97654a4d703f00b3e550010dd4eeac79310f4fd62578f4dcc128a7dca063c55b5831b55913a30cb37501f8e07c0fb2013685202063973879f5f045276485c987159c0fddb62ff46799b2a69e0b73b841d9e854c34c4ca2af20ad5f4e8e00ddc2e8ec1cc748371e14be11ddcfcd7af488b8d1a18435296a68d2e6d95b4e49fa01c58995f18c70dcf13d4f28e15541ee263fc8f42f9e532d932692b5b2554cb1ed9a04a5ac46435fd38003e752005f74719fb7ccbb845b8571b25f6ed7f102790cb83419a89a769f3740df616afe8727a6dd86c76d5a1b0e293b2b94499795b7065d922374087df06729084d10371a25cc6f3efa3f97a20b40de605e0416731e276e6a9e99d960c1f360879e086238614aefa350dafdadd83db85e5ab37bbbceed05a31ab31790e3665daac0eecc73be5383102ca545bd97d1c644e320077ec43427ba5d0d035bdcb4b5432eb243118baa730fe9ba3856f575d19e4eb5b07f38045eb0b7880840edbbd76574746b5c7f15bba83acd7cb6184e876167e3d029948bb16bb4d2b3d3a4c0539a6c39a03c49a23c66e8b008d0ebffc6adcddf71c441c8789e7af9e405fe0644d706505ba1c0b2add7e2520ad54c8d97b3532c9a1f6e6603039b5871d4176738175a43776dbd4508578685fabd34ccb33dc705f11daeeaa9726855d1ceab1665a1eb5903a5ade1f950c66acd8fa9015109d3241e0bfe7fb0d320989d8944cc479e6d62337f381f53e1a0753f86b411301cd3ef902d2ac185d2763621d60f207f174e379d6d8dddd473c76af19d9ee322ab162696f6d0f9456e5479f9f09865b23b180d2001d3893d529f85d277b60cc7dfaa43efafb4f46baef48e4d105c1c30839e38b06f2098cd49e745f4bbfb517dbc861610c9661138c1c02655d9436da5f3e1781796a37affeb18aee85f2f6aa58dc34a6c8cf3e0919aef290b37b15a3827b1ca3379d06e6c32faefaa5dc9d557d2ee7b75c9a67ccf0bbdbbf825b2606f8e5a13ae52d8d4b37cf859f632f9f92652f0560105dfcc6ed741980de790ada85c9b923a5fef8be7529e5295368bf0662634f052abaac10397141fc75e06185d4353d49bd5aa450e96034de784d781961292b14095fb9c20679a2c093a27f33c6fb72e7fe7b707444ee92c0bebafce7a7ac9e14327a97998a3ab02600a10306456ed6f436ca64fe7f63b9c08d8adb5801e403c9ca66029d7efda20cc4bb90f781b4035b49faff91705341daf9052e0b1677adcb127a195c25d08a5191cd7640f0b5947cae2640b8b8f2f2aa67237b66ab3b3be57a2a805e273c1c649c0c0859d5dd8f9bb41cde65cf91a9bfd6c90c8f9226f7ec48265ad59acc4549e5cfff19a4f50bded9ca5267a7654c07325b83bf61c081a55a7eaf0341736d43ab5ca5985ae02a85970cc400483281e1159836091be5e86ca18d13c74953490730b461d92f0f6e94591f9ea8dd7977b81843a6771e4c6a1c3be4f0b9252fc6e2cdf14709e209170988f26d9f829dd6d06cc71dce6049d4565e9d76ce24d9fae21e2bc9b92979fc3135073ba5376b928d7bc84a47f779207a42b8a82c52428dc07fb3e71cca7b49ea9f95ba6e9f140bf5928f9434450da06373b6837f11db2255100780b844b0a731e8da3aef46a9f137657d1499ec33b1c29402d75199edc26bc15169f11dcfc4e4d5d0a6dab1d8da64e39c0cec91e76766808e3a84f6459c900eb06f15e8c53c118bf771eda39fc5a9856f2a075e8c313aa027797e782102e3f36c433c871cfa6f11ae0143da5d66d8b32e08ba1ba9359c52505be5b6d6639afa14ecfe4d45111214d6e77e946fcf8e32593f6491d5392b2525f5dc12a16ea3d420ab1a00fbd918d59cd66be580964ef4c6c8200376150b28698ada0d23bf746d23f0334f6f740a2b6a99be08d30d59d9283b4511ecfbce1e5e73e48b5fe159bed9f05155d563b36b7145545a6a38e8342d696ee3fb35fb5cd15e4b88437279cd993c79f2746e11f43a6451211bee96a9ed3388e7836955f716ad3eda71ffa32ea6a421992f1eefd808927027c81fb057b02762e911310971aec7fa0391f695b100c5ea2b7c3c0793237e02571b210c705b00c3f78e6dbc6169b132522cbebd9cb13f2230a9bb484826b9260de06abacac9d4d03b3c0dde758e05fe8f403c5330ce845ee967582e5e7906c5b9a6ea51002d6b699ab05fcb838cc1e8b2de63443f43d0fe18ec3890b452306d59f45a9b55a3e883b1c81a3c9137e604d8ce267a9b9046ee4b3cba1e7189cdfaecfc9d5e26b306a9005125a5f4cbfce7e62db74c112c290cb3df73bca8a501a29423d1ce09eb6256d55cbd8b82b79991c3996b1593c89f17c8ead19847951af225f58958423ff9f660460b1976a0c337f504c4e9cb7a3bf3e252d0223d27b082407560be9f17f1ba65d6eac0906f9ad0f39678c86a4560c5364b57629d9d0a29fdf8448a9a26fb8cf33f315cc6fd75dbe735754103d4e0caba58e94e6cbacecd3871eb485de7af8abe77ad61144e5cd27acd52e882ed1043cc19374cfd7b0a17ce2f8b2fd4b55460144fd01f1175cadb42361e3adcd76865ab7020a8996422be02019e503e87cd0de8edc43d5d53776a2672580d31202751d6c092ff1440c01300bec9a23471c35fd85c0a4bb7993ed78310b5fabdea8380356ef75e7ae01395f0c435d3d25e2937163252ca1062f0fc7e60dc5e1e1cb180cd71dfe2badaff6006cc8b1fdc544d066369021625a64838fb04634d0f69a0ac426e64d89efdfe751359a6de5706c6dfce69950a3685e65c64b6925fd7c982f56938eef77515ce3d5e2fcea7829044442b1826318ca1f316d1a60abd9272f8f38e4b3fe37aa5763cb517ec346708ea13c7e5d43d5c266fb7d8c170cefd65b58c3f0ff485dc9337e8910e5766f35f1e64db5fb209ff7a6979ddc21925ce97f130f3cd54eaca6d5be1e37681b1bc5e3f33cf47f994cc6fd306923d5c823f02e2803bf09d8842db3f1f7a92e9ffb5817b07c94e23213629a465602d1635f4248cee4bf82f8e8463cfa1c5d3607acb15ca7f525963eabb13cdbf656bb2982b5beddd67ac0243bea8467509fc191ac51e55c6accd9b32940c9716441bcdfe775583fa49d1be32cb69486aae7ccef5969c4144b17f61818d2f9cc8e0859134e60efa6a739f827604dcc1d93db958bf09e241435c39d045f7e74582b78135c0ec6eb615c2c7377ac4ca187a9e13e7e085259066109623c5d3fde5cdee79b3ba26e3b25ebd0c17bec1ac12f0e8bf263a2b4e1bf6ac7e9a2c74f084ca0ecc2071009477acc0f66bfc21962ce64fd6cb631a03877ddc65966ab4f1cc969977bee2b38e6a667ea948b286a5f90a4ccddf71908fa4cced22d7618559a5bd2903c9c0fce7dc18ee46a1a25c006a5abdc7ecf4520515f6125a80fad4cd9243c883b3454b6557fc878e6a7a0be610ff2c86a947913e200cc11f2ea46b1595493a456b52b0501f96feeaec8759f8b9597873711cf533f0a707698a8f77eb8b6f1f09c97f0baa4626f6a86f6090a44a3da1b5baf9291e2435d36b3218bf91688b8b9e95391eb6bfccd073f3db367137e5ff7c9feb0003aa69a539eb6e5d07608feee0f88645aad195e6e2a88d646510b13646f74e67511af1143f6ed344377ee877f8e3c69030055a672619e090cf7cda16ac821b207ec6e3fb003b0021f051908fed359694aff46644497aa843fe1558d04852fd6f0b28b6df22c8a47a5cd1c592d80645eed5c90464980877e8b777ef8b856fad79501a25b61b234491e274eda582816f83236b98a39827118a17c9277dba6d8f3c4fd90079b778d1fbc7c2058d95458ec1c13c3b1c340ff55021e484cb9e3942f3d1fbb02843ae93297a0a106106f3cf2c6963ed866ee82b654a11c5ae8a3ae105803b8779c531f767cd9cffee4f97835e3abc05253869725dbffd354467d9119826bca7a483facc9ee3d04bc51987b268de5ff5c40e5499a6248862d4086f3079e92cbbcdccf22015816f1b7c520287aab4ff1e2f072509bb922aa870ed7164b079262ac86cedd30e8050935f6890562684d7dbac2bb9b81ebef6e2165fa587d93e498381d9f41fade9080cbe5eb51c8fdf5d2064dcd2073fb424f4bd0d3cf6ee1fe939bfe3b095e29116339b327c77c8b26feaed81f9327bdfb0ff2c9f750164f68a4dec3f6a634fb84134f4a2c314915a430842f14062209f1e4eda10eb3bbdf7a4c9fa61136ea57433b8cf75e7ab1c44834fcdb803f6612ac0654561350db40a18fee27b99a60709c050737b812a4b092637cdd007304a12b0984bdafbb1b2885a754d76eef40e6319b77c8b0439de01627ab7e6a08986be67d02701445d7e5fe56cc49c85e6da9d72c5340dae9ab18e732d1f1aaa83df22cba4affe798ac6de0f73f5c3e36c3e4bb37990dfb7d3bcbe9ea0473719ed37b61394960a8b63b42009f87bfc6cae60186e0d71191f013ab68238e210b2008505edd840780dcb45ca2800cfa1f2de01cd718ff86dae4a87c7e3b92c8fb3a1bbf184c06e95fec001a5fb029d8631c7d3dc4fc915b904133df643ae4fffb9606c86b3b1606f7415c4fd089cd04d03ab5fdcb541ea6a5b51e8466376366900b8dc1001d5a04f3f44807b1da09c941ef0003f16df55e8db7feea395ef68e3dd7ceedef343d5e126bf323896f8bba7611fc116ae05ead5bfc201ac241b3922187f99f42b15f9a46bb30933f20ac7f8cdac47a86d47a8db0da557a23d991ffe65f059dd415a5bcb5b3b2acb37a683e9f9ed2f3834fec67ebcb3db638901631c55fc1815f07c23eb67e0bc816eafd27bca01fe4cbf3f8406ce0321b268c0cb054206796606f2c9411d3496b70ac474757ede6c22ca1726040813d0a5a0260665ab0534f09f524a99bea7f0cb2190b322a9c658f2f9af97e3a047aeca79b54586f732db76d3a95c842fbaf68ed8489f21e0bcabd662a5abd694124300747a5dce930bcf1ed22fdf08b2b27f78c02731880af70fbb02dbf76170a09b203443a498cf2527ab71c396d0927e38ff4b50393afa55108fcbcfff4b991c743bc77b891af7d44fbce1da32e6bdb2083f7e1ddb515924bdd3285efdbbfa405116e5fafc25e48aa470b9ea870d68a580082ed530eae509732f475ac66971be7e020b00ec39465ee27391fffe9bb86261bb0e951363d5188744958e497377d9a0892e85e8ca23645ba8524f97529783d0b7b566f47fd7bdb57d531304c2ef0cf12aed3cb262c8181001ab96a912dc9d211615cc7c9a6a2171ccae19b7e511c84f279a7beffccfc8cd76af3eb6c7e82c633d022f85f746b10bb5fe9ddd21d3046a4265eb7ac463ff7f05e03f9d518b39dda15d414b6a602232ef17cb345da2a0cc506681c5d6eb885c0f95fcc21d4852b2116851196de02d3cad22936a851d806ea6fb97eb842e6b79c280417cc16d277adfdf22af0b0c741ce7655ee21e781208ecccae534bdbf9dc9ebcd9df6ed5fa350daf9c781115ec9d8bd3d665362581927a08a157e7da129027d88bb906fb32a02c9203dcd7f28074ae8b1ba832b39d4010bee86cab22cc1d3af7fd551fd9da8dfd6bda56c300750fcc854c4faabdc4ce6b945d95e26ebee15b74b76eec41acb3842cb10f8d3db76d08e919940964c08a4401c1fc4b7072205416454c05a8e9e5c7a883ace15e2f5af62968b15adcb9c9a016031277b262fc59a0583097260cb7f53b3d66f9b7d8433f7ab49847ace0890d1a9aaff834bb6b94288337105225462b9ab759afc2055b6af6aa55688bef4f6d229f64d68cd40df025c8ec8c99f89ba3b1d170311c0f115946cb7d84980b755005c11a29fcadd2d0fd5649db867a2e7f74d431b4a56bb12ad17c2b0a433b13a27cc3eccebdabe934786a9f4efae20138ffde55993b7c20970934e12cdc3532601527c55ceb3abe107660ff4a32bf792aa57586dc7f76c6fd25d5b16504519f6b4d8d079b31505ba7689c9146e356b94984d57ea9f6dccaba757d71e95392694a9cb006d0a2598645e37c92a545cb3a6737d6325e2450409717423571e8ee3dc82cb2cc227305778ef46c6f5c9ac84ff893aebcec2cd6781dd69df76ee642a4ca0723baee58543bc836e1ea3ab9267258e632baaeebfa07b093fa5ca90223b1c869db68fb10f6fc8a2ea7c2f1229dcd8f4c48608be067e26485ee03d67d12501276a770cfd4f613df56417c92dd4da4007cfe1ee7fc70bc9a44a8e07a1865b04cdb72ddca371cfc40aa9f8955909d5a0a099e7ed19975f573621284e009c54f3543857e551b02d80134b2d63d29cfcf2fbcb14add557d2bbda4bca5b9271187255697783a994cc179ab15bbc99fccfebc9065ca4222e8a3b53d2c400853a9dcc919a9d729333e9dc45b88b58c3944c759f2c53aa9d19bdc09f5a22b578ef881b910008c56e2dfc08f7d0d7230070b1b986029373114b1b238922422c92e0fea9f9437df0d1a6aad42d25c989c78396c8e498fbdc4292448cef46f8e629a6e465676b923bd54c895108fd72971a234fba2506b5f034c2d87ff062112c19a1bc2e06f91ed629b1f8e75722fdd23677a2a6d8cca3625fe077883a567fca276860e4952faebb58ae3a02594dba7d2652aa0b099e01e70a8dc7c2ac3a9f03a1734203803a3ba81bbcc08c4c26e2f63d9dd4ddd3b6e551703daabab39246b95ab3b85c60ba0c1efe3ee69d09295c8fe6eb235088611b7cd8cb3512a417f515813c32159fc6301b83f692e441eac8c60d9b64c28936ac76b6cfda0ad97e0fab74b2d89b053153f097a881590ad440a17cb61d4b25c108a81bc9652e4371682808c2d11a9335b62ff6de9720101e15de53e882665cc12049b9b0479c70906e157fc41c13f432443483626a2db1ee6c5d52d91a5a55b1ba0f38c006d8a7034ea016ef8b29cd85de5c8eea4c6c69e4f64b9663e7cc60d3c1f4ba61c10dba65bdddb3e82749929bb6df06d40b19fd13826cc0aae349be65f1ddc3451c4caed7df84ad9dafbee62076afca6e7f164508154250fee6decbefc56d7be3480cac3ef3092c401eaea1c89b7365cdb3f1ddc7f0df0246c1e0bdce12e6cab807710c041ff0eb173301eedca50007651df842c1548da367bf38cf7dd0d1632972168e6429ba7bd19e980025c0b8997d40121e536fc4e302a66dedf1b5993e4bfb05b37c5157d1eb6faf8507b650baa8f456d53c4a82541cd907ac242fb02bddf3913adf80f944a88fa25b3f5c3214b03aa4a5e7074af185f33adfae46960c7258595e940361cba87afefbd136dc1d8f6a599a4d8d6d4d4118031cadce5ee34ab4beb1c5109dbc86c9289010b8c5fd46c20298e4ea495cce5f7b6dc0a1638c5c75a01911618f9c70b1b42e21c26d617801a3c5a777e6c6119aae6d829cb83227054c6db48c94373e0ac07835d0ff2596b44ec46a5212fa41a3ff6415e25128bb70eb5dec783f633ff10ff9b2a19c3139847563fbeb9bd3e9d661553e3991e9cc4635f176eb774cf9c23fffe137b1b794fe992d55366cfe6cee4d01871b21f2e81f5010188340a25733e7da112201cd58e0ad0707b1a144f9b23a10c20c9354219293f3761a9285163ebdfc464a99e310651f6e7adea6d7dd1bc29c609b48cc7e645a035d32ef43660b748e4b0645c2bbea1dbfdffb062853176a9633cbb7e50f86fcfa2fc3d129485501441625c13da11fe2f15c54d07323ee83a32e7421c85ee5516fbe0c81cb4cd5dd1b3d9a5deb1ae21c1d83c5f4708febba9916df668d2e9a09df2c84e7e66aebf64e5da8a38d03b9768f517d7f5b5cde232f49ee4ddbcb6b59d01188f7302920a51023a293b5653f0339c126b13e7456b96d9bf0ee76ab3c38af5c4a827a231912b0dae87cb254351382f5f1fb6c15e4a26fd94ae23636fc56bfbb084d2b7a5baff9d747d3dfc9e8929438eb76442be29ffe8172f5f32bd9e29c03c7a0a84b58267bdf4e20544bbc2fc9698e0856afea7ceb779ac81d09f07990104d0c37934d339aa55a9a39dea17cb1d3745744fa20bc8b2a7320bd7fc090501a809310bda2d45700a80f990849b43e83ce94f803550b026f1b61426daa0f637241aef89a238f81b5abc22d44b954fd353e795614fb53cde5eec509205499a17203759e0a091874d39b975d234b541f66c2f8cc0b51b2d6dbacbafe0a3cbc77730fd3609e68d6bf8cc8f32a1ab42cae817065e12cb0657e6ecb86cc63e55857064b91d2c1a55a4579868d3add8d8de9e8bcad359d5d8fc35ef31701df96e5242e675acdaff7e3f8489e36d352693a8d4f7020be6ca047d8b3dc156e019b16908eb981e5cca85b4bbcd3178af2f61f2b9a996e4934a5efe6a8f073f1b9c75b624dbab9bbb671f961acad7d2fdf17b2c607abd2e102bd07b95db1eac60dc9a58cb44e9aa097adeca0277d84c36f5bbdd34aa739b1af33870c162dab065d9fce1edae6e16d8391ee9fe16c00a09a83b161dce91768c66b41ea1a3fef9d7971a9ebd48d8f529bb3b2d62d3b917b91f004646f2b2d52a9cec2b353fd893379003bbc747ccb3741508af9f7956202d033055ba74eb1a78fb860a1f84e4892ce217a694cbfc868578f42fcfbc6e66a2518da241de4166cdfe792f51ae69a8fc797d608370ca96fe1069e71a8b6fbba0e1a709ca115df5c65419fc964760205268ab826d558bea2a17079ec2a5b6d6e0a27fadb0ae9313948ee7722e9d3d77a9dc18812c6c91bc48d2363748786f2dd005293600cc980bc6d8675c673f164eb30fd2cdecc1da77e097b77e49d06fb3fd1f9a09a285c67a6e34c3de9e6825820cb0a63dff91ae7012f9be36177292a8d813a606b2df4d078ac48091cae21c5179a371a472ab58b60602919f6616a2acff13e3d5755c4bdcda556dc37429076691d347f9b1dc1b3b6bccdac01d1d4ae037424257870e2542f957c679046bf42215e88fddbc8a7e6b70a97057119b0ea091a57f3554a58948e0c718f6722766a04eb7ccd4a4dfbd9cec1b71cb5cb7cc863e57ea032f0753bdccc8c2d658eeff17e68a48b9f2a25fc20f642d9c2816210c79ca4ce464d4cb70bd646c4f0ce1b469b07d9ca8c50f6a3c5ca55fcf84de555cb4202d09b589bbbfd53a63b80865044c378f9e6c8403ba7dea7ea54d881d4e5780a76142df62647a68a6683a13dd3b427ec827e88822ecdfa1307de9f6e19b606fbb21da3b97f3760f1737e24f424d94e35fdaf96b3db292576d73e33e794742bd60ffb91b8973e69b1ef69178d4a89812f9de7e93c157ff6817495bc07ec4268708d9c76ef573d31a3c908d2f376499cd322e4d42d3ad3d58beebdda14e9c3c09037027e2f036b36868ba18b1a07f639ae68864cdbf27990c98088c97f8271c1226715a6b85658f5a0497ace496dd9129a33598375a1872090a1f45aff6aa9d1d51b70ad768fcbccc95486dffdb5b0d2009a6463f02be37842e113a82b479ca5e7ac4742c40fe392048ca144f4837583c42e42fc5e5dcf4749ac4bb7515c45b25c9b5a82c15c71460ded42fa5f421116a970dff1a357f85a0f4830d58eb6a889d094649cf77ef1033382fe44239034010fe68dd2a69192956bbab04f810061a1b188ee59cc1b5f2ece77741666caaa3f38ebc75e67f02305bdf11d6c1802060a0dc2f8ad88518a94709d9f401f94857f7ad2fc180ec0f84bbe157eef062a167a563b4a6baee350f4f3b612c4ab5b473874737491199f134a79ad2e759ab52365ca1c1d28c2b8b03e338403645263d14e368b85384fc25011af3f82bba4d2470ecaed5af1e4660e83e178b3886c2fa5f061af8610b7efb2d5ffc78ade305f17733bbbfcddd09644466ca6c38d7bfe0d146a4fd51dd69a339529d4dd6b40963ff769b88e34ca0c9ce286c14c9a02b0c35021626ac1afa670a8e75cc0b8a294fd82c39c2bbc5384391978cd41acfec05dbe7d9fff4b28cbb753c5cb60e02fe3e8be54d5cf7a3b4c7d9d9d0e4555e76cc96bf7b8bc15b6eb782e49dcc298d9683a96edb950c6a638fe0e1f13dd9792e5d55c723a0428f10d0cd7443c2e61e855a0b07bcf8713e7ddda0a3743e798e53409da6838a6a13fb43542e1b6723c1bd1aed3931b4bd02d682d0200409857248e7e1d8ea03805f0f4d415b2a3e12eae9801c9e914a013093aae8d9dc73b6204ad513b65ea0ff5633ea80544f3160b41bfb994cd59d05d5cc17515453aab8a9fab1a4dbcef951596476c2c5a96a01e96a81104a98c06992bcbe1bbca4a6b47006534df8ba9608b5d111aa4c2fef78ad879a809588b4e528b802fb5336e0515ff433b613a9a9b98f5c4b46e92dd47cfa39a2cdbe180120391cec549127ca67f503dc38351d003caf956b2c280414bd61c5dd5753d57f219e886b1ae1ff6da08e6f5723fb1b0d36fb1d8441bcfe0d757c33823916d64257a126ed9f8cce32b4fa60cadb0043d1958c0e8720146bf4c1fa93a6ec0b26971be66a539563b01f0a73ee6118d130c6607d112f7fe2d531c92f03497a054cc8012a8ee0fd9be1f4279412b8d458a2d0c11788e8013adcdb36027f9c943907faf9d187daa274bf892f9d4894b8e369c4d6710651c9e1fbddd6330c63aac2b1ae07b44e3732f79e84c49264fab5237c276316603a353bfb84fb0a19bb1c096947e3e36f716d66e11180f9a6685d733b0c2f1796c9cad57dee3235064189a2b7c1cc046d620373e5c9c7e3867c0c22cdc00b84bf8cad7aef711a612de89425fc04ef3f5f095454c00ec00f98f0cdb2a3e3bcf33eb657eb572218fbbcf391b6de26eaff86cf65dda38a946244381743390d518a8d2c1e1a59f64d8f01204e539e22a4c3a991bdb16f0a0fb3ae87e9b4f5e451a7fb4420d63e6cdf5ed72e8e4dfc0e3fd65b0ce5b1415b7500e5f343c225f55cc27bad237886ad09d90d54e49e3c58bc3fb0e20693f7ffd553b319c1126c116c4a488a51591184741eb55c57faa1e266abc684d7994087b4bd710f900a3050f134a459fcb5c88c1d2d05050bf3e3f2e3c1bf7c6473bff812b76949f89c287a3670f24960587b9b9eb953d703743df203a657a0ff85e0e19bf338f9cae31d7c55640aef03ab39889c85a7f86cc79f220590557364405b381a6a964135db483a5879ef119b3f2dd64bb10236d1aabc41283764d69dd29285ebc0ca86f12d4eb09f53c4947bc308ec37ed60fc5e8474492fa0a2770482d0656df8706d161e0e8bd0282ded467e7110d26b3db5b617fa7c5e99462ae6b55f9167104dc363d295a4bdb7f629f37c33e6bc4b67a5662639b1ebefb1208d3e20c5b51324312fcd294c326948049e522ac63087fbc3758d322506bbd6aade0043bd017cfba2d815c5a2e3aff56717c805ff002590b9570191db1d6a18b2a5af94f7827a30e39d17f252b8c068648cfb56e305db1ecd1f6c10de326ce11e852c6fed58825aee06d8efe33ba0b59b9ad732e291a7b51036dd266e0028507bb9f74f1cea4b0fe4e27dcd2cb1a95d9a79de7d13856c0ad5cc1ca7dda7752d1e7447a5e2941832f40bca77e8b21c7a2268bc7c267fac63b9555c750256ed7a4fb9d96ed80a65a6df1f215a73a049dbb540255d2ef1eeeb5853467ca5a411c4864cb3ff1a95250ec2b9d1afa26818703bc591a1e36a76c44ec32a122153c6308ca8c817ff51be839f112dee7be957985251ba2e308eb3ab6cc1c34a28110ac49e3ea0a77aab0b93c54c400be876da7d8a9816329fdd09d94289ef68fe1e0b7224a9167545d2236f0215821523e1f22c3f70542baeb320f9c593a44cb89537fcf6ec374a09347daec0378f7f17d3cf55302e4c5f9d96d5efbcaadc7bdda13b7aaaa7253c69c895c6fb40db61f5687432c49523b2b2e62077cb789ef0c2e955d85b34b8277f0229200f2623e5799d660b91e9f16dd51ac584fe36c1898a1dfe9e6808afb4f9c860517f11e02f6e84a9b2291bbb29bf11fb474a52f1f9fc1ee09deba18a7b5e96e5ae98006789a11a203076f4f601313d784a1f3a0b4fde8114d15e5925040439a2b035ded6be18548009ecf177c07056b126644c3ad29b16b6a2e686de23170dad659f9e23e77379244ab20bcb46559cb6b3336ed74c4b2900e486f8592438ab5b307c252ab1709605a4e9dc919098aa72c8d81df597080a2612054293143c38f9aae129e5da44cd7529b183f1cd8df14b4497a93a5df40b6c336b3d5f89811196556707d12db202e1aad96bf6a1804b08afe9e3dc035c82e948ac58876b7243e8caf75da9baaa844986438d4a8878713ba5f949a6d345093e1e85e5ef16859b15cb31f6a5639fc69a1d2402152536a2e4562eac548cca071f0c23823d3e00385098c4a5fb97f5ce95467dad35f5373edfd15fe6a5281012c76d6e8d717facede866887728fb68359db3e2a879fef16bbeb5159d31c87e043ad7b9e7a7c2e46dff752a6d117da6bb418d8de7d4589b8a8dac89fa93409e29768491f65379e7471cf32f3d6141465b95f637db32fd31f697090b48715e7bdaaee77dda8468b6da9fa167e365ebb858f0c8594e07109d24835626915fa20a1f032f760c04345fc74c9cf84bf926bfcdb95d5ff11e7d5b8c6b6065cd31478535a36ab87b2d25c416351e0693c440f42520199ffd259100caab6758575d9dfc4c70f381d8045bacf93e34651793a98be0534483130e8d645f74561031ba5ed1c4b0f445286b41f3b736bd8317e30dda92ee1d3299dc8ead10b681338941875beaa465f5282e0b79a02975958ca5cf2bb69460bcd42c932c69e4fdff1be2de6bf66194d1f16cb811117425940616a74d2721c766ff610f95f97e3c4f3f89dd2d93a176a75b2cb493b91bd9caeba00f6cda4243793c963427548b7fb36a6ce7bbcccdeb21431334cd4fb89584c801e7cbcdea7ddaac0e284558442d664a75fa440bf224a3397cbbaf3e3482748d04a0f996d48fe0a963dd3d89a1abf6a3a598403a917611769444de9217139966c2b2336bd2da3d04f8e4923093d9c68924ebe95b39219299418fb39cbfbe2914d2a8beae9e0dd14d22024af21f2cbda3ea96de060cb5e1351512196372e6a7ab498dcda53b4d151761a54101e3be105907619ad316cd6e9964fa257c69de2cbdaac8c8e327b5624b59a243890180ca181b6d1331892fcf0351cb9d21f85eacffc08492f6a65ff53b789bfb26b860f649cdae11ffcaa3893bb86869be9c1b1f102d176101fae79b98f9a6631768336dc0994bd861f12b1a1a2828474b8446ffdcc48f82322e19193f1114a75390970086ba91b02d65b99f4c36f33f34a39c5fb3cf815c3098fd4729c7d962aa65599e0c9741b4b3af47b0110386f4d7c165db3704c282435bd51c0b9859dd363347e3e886ee184792f2727f9a74c8fe87c5244315bb011d3f5d7ba86ee74bdfb84974047596a1d5b57bc015548b5d61a110a1aaf66e4a82e1b2b42c6060272867d404b686c967748a9656376e1b967088146ba575586ad3446c7d87d406a707bef12f571eeec52ac43f102cb31b37cb17b9a3fa8d933121bb63d17804d852a473db629937821d7d6881d71354ceef0f5a477a5c46c16c4fb3ec285dbabac820e48aa415f10450aa70fb9c20de93a26cf4b1270386fdc8db74f2e8fe6fa1fe9eaa6e73ac87d2de36c3d2fda58379d6599157a712146ab0a74a346ef5205e45013818ed04986a62d5c95b7c126062a15a52acf097f0e3203112a0f63317ac03182b956a68a27c40b081bc8bc035221a0262805205526e8b121c01670c4d9c49e11b195d8b00fbb1337ab3b4e417f726891f80f273da99a14b4e10a3e36e84b1226f2c40ad77db9d429aee8768947a811741b4e2869199a848974c69fa8400478a98f7469c42628f948b372fb9039a9f1f68f10167a354d6344d3ebae7cbfd6f78cb44ffef93eed95ac10875de27ac413e03b0facc93cf68dc206c9066fa1e650a7c0faf2f77f4922f588ca05027964c37883545d40c31f44be8e729b90939879b5744b15b015f6890431ef162f62eff35568d1c62a61917bef1da4ebd904dd7ce9dc8c836b0899fedd32ab394c536a1afbc29796c8bfe9db6e1c778e3e09b65d8993c97863b457c0b64a3bdac18269197a5bce31a6f63d29914f46210e23421b72a6d7c2010f6aded945c682eb55251a5817d04df3acf62e64c2661ecf182eb38205066bd54dec36362bfcb3c38897e2a801f85151ff001454c9403ea4764825477e62c7eafb6b7db381f5763c877b226553a23fb82d04fc63c822256c147928de68c1a1edacfe7b703409fa6f14af86c506901d97b8ad7b1e178c8f6bc20505a1bb113de757af7ffcabc40cdc1a1d445cc50e14da6b78c0a9f5d39e2e861b24584705a4d27d40211d39c8bd8fbd92b16a09996f426ae6049029b716332b4b1b014d9fc620e807ce5a594fbd9fcc3d1400fb8c6193410e6d42236d50727c437e887c1ca972722f48548138d5d447e388274ee929a65041560537d7599290dc60c40e757982d1529221ea0eaeb07ddfd45865906cd8f982388a6b628b012614edfe37e5def80a69a0cc7ad2a48973e33b1e075c64066259c13245a9345c667e7b0eb8e64e28cef7ecb8c20a356209dc5c4fed1e0efc927d386cc1a41c822d0b97a2d3f6a92d5dd2c1913137347d7772b4e04df93670a63adcc5984cea0132eb4a1b91a4bc982bdbce3a90ca90ebba6f8f6e659c126bcb3af82ba02c266d5032aa72a082d4bf5d94f7356971f44336ada0a238cbcc616a2a7d9c53e95408031c8a1cae545aa42933bb52c48a84260d343fff9a989837a9ed837006c6194090eb50a57c88e90ab226642a102e5a0e42d8542f358b423577e4a42520b61a57f87d998520a05b5d6735a874a99629d313d27e87fb3627677a5c82bec79cf4823062bae036e694a413877a8abc87b8e76344fbbadc855e215dc5daab258c7a37e9283e245d0a42e6e21d7761126bc0154494e91b2f34e1e7f71ef942d9a6f00e818d05d2ea4849c82b0b56d49d394d37c4667ce4caaeb3d1d09133f90ce786d6f8b5f46fa9ca5dc7dc09226bbd71621e358384ae1c03d127488ef05d61e80ae6247228571e1397796ffa9923aa9268ea3b8a19cd120437e91a734a99cd0674cfc935964e8d7bf442a9351cfeb9e32954a3c9e3c08772f9374e2f36bcb831cc4ec3c975f6303c59ac87014c8b33697397260cc2e4219d2d2b9e237c3e6d44ed98d8872b537654d957ad2187178d438a4e2885ef8320321fd5485b6a990f7ea56603c85c4ca38454829bdd6f25d32d205766cddbdba7f03610e61b652408a87dc0a4b4952e192d3be3b03551fc92d636d41956b35dfa003f571b8b64024eb012d412035dff12b02b12a4ac5c18b48015674421906256f29ae078e5424d180e9697464e0274a44f2d5b67aec9b379c8f5bf280d306413e644fea5bdb36940c25100f6c728015e1ac028014d3f4d4a52db243591ba9f036092cd43e0f9cc41785b5f6d9454a9f90ea25d9b377a0659ad52d1604e9ce8c346ff18453d2dfef872957b362070cf98e73fc9daf1ff856e4554454e53bd6f7d9ccf78f5998c0b45cfd4c2f98821d5f1c51364a86fb5e53cfa9232f9fbf67e25c3f3e6758d5044814d1f165297d6d34f65fc678fc0d138b811c5e6d11c0822c6b00973dc068ae66bfaa2fa742afd1ce0d14f164af4cc75682b0a27156e58b674c7dc4a72121d9f1ea865bc3a15b46d002777f9a58044eba9f62b1c32e32f6e965a169f76dcdedb91e4cd16ade57d98d2f1e62c61c84619ca58166a0f2123d645b8b77992837a3c0ededcf9ffd1f47de87da3ed2a1607e2c71791007430a6438a148d2c5ed945646641fa122d4b6b937eefb31e279885c385df116840e012e0e23e5bf7f3078b2de3df40b9085dc9276d930260b8b9fa9a3690d3a6f9db55ed940f8e001ee0dc7e23bb0d3c2d5d1cca9c5d0210e06b046c822ec17672cd75ace3c24516baf15bf6b6c8fa9a1aec620ffe8f0acbea92cd699a65b06b7f1a97643d3875cd3152387100986da3f75ccd152273bd145c27e3832a4534e116ceac0c1a9e018ea38f1a48f25d84dc03cb4447fef36d36984e9f261855def5dd0ffd94dfb6c7145abf98e71a5e292ad8ea0e71f30d0b477d3b51a4b4768ffd003c31ecbf932203b2f292ead6d3913a6e6f2b38e03c7b70070ad5fb2278551563ebe31528f90c4731db95b1c0599d72b2488f739341638bcf0dec6ec99afffc778cc660cc4d1d241eaaefadf0d2e3993bfc9e8784783591f78c6302a6503f4471a9a1a9fd9b9455c5f486e28a63985e84d52e37ea073f5357d9a5a40b98f48a92f6c07df21d54d69751e0661772b5e2fc08b3c767d6af0ddaf5a221e400341dbfa936cfdb9bc7e319715157c233a11ea2b5c6977820bcb6c2fc0ba15c11f12b2715df5c2712fd20afd2fe008bfc55c535cfe22aac2e0bd25c69ce456396c91bd168b29d33bb68318247c90ede231a0fb0e0c1745c71cb8fe94afe9f5f76395127d1c8e767bb8fb86778b795696f53cab1b60c0f5517d2b57742b42eff46d61b052dc21204705e5759499214724939e98a43fd3a27593206a8b117b9e0ab156f83f511112dc020006b3ae82be59d764c7ecf38cd0d869fdd29720979485d28fd6e9b131435f9f9021984b30d721f5f21bb88215b09577fd674d878af90cc74707510e8fcfa68530e585d6eba9381337d7534d43e7f86fd9be9609016260c7bbf444e8b133ee6ad2a687e3a1460509f9b44e00c8a75e6df58c324ebc1cef5f5c2aa5d4a7f32472991a3aa7698352479fcda5abca88a3a9e410d36318d5b74e314e5ed77bf61ea7ba0c5b2adadec1c0be951d1beecc76e1beb28812bbe9df4ed3ad970cd99ff56314bc2d511a913f2c027d040455a01c6fb52d4f08fd68fb6643af97e0592b24b315326ce56cd40b7984640cfe3ae73ae46b4c118f5660b65b81456a6b17be376de8f100e0f52954a924ba42a4ea1d3d011aeebf678e458dfda951e5496e86e7ad752dd6cbbf3307e38409591c437a4ebaee3b135c305e77e6c811a6d778116e962e4b08d86c3d5a92ba1e056d9be04e52a5dab31f8e6cfa69bd7250625734a3290811b68b649aa151f40fc09dec467d2d6143de48326efeb79adf546ce0e9b8c24fa0eaa96340a4981c9c3a87ba880f7c71893b5c3a54284f0105ba321a31d08279f33c04a76bf5693b000301a449c5ee97fcea29c9b567498c083b1f62de85af2798d2df5addf4f0e43c042e556cff41b5a2a29b0044598adafe4f7d3493023347b061b679946350d0c68a4d9a52b3fc29791df9e73e64e27950ebae10d7cb82b653c98e2ee97379eb221e542fc1369f64e27aa2efb446683ac602b309b7d39be283183ae6ee6f26148635aee6190acb32acc322d95101470339ac271f2c03fd73a060c5e51cd0de09819e6dcac7f3abd8011a4a520e2b367bc65c52847e7784b72ed55b56c0f8e70d6a721b10cbba18bd38ce6619ab92aaa002f17b1a2075b07bef4bda1513f7054f66ebfb1b02a344cff3331ddf9324b9d9280009db7d138be86310bd2b2c672ecc95220d58d8667c5396bfa38066a9c6cbfa5a77cdef191734bd79a9181697cb00f0682d5eec6c8ddf8cc6980c842339e53aabf655478610407dae80c3eb7519c880a2bafa24c82c4901dc3f3a28b172da480d8851ff622b8dd597979ed604f53c2c7646318423d07e324b85726c32bb026e4038f5f47dcd127c91fe61826417a46bb2bc482a2f6bb153b7d237409f6e252cbcd2b5854356c7f0fa412210d77937bb71abbdc646eaeac052200cd9e276fc433b253c86f378af5ee24d0b278235c755f83e71216e0d8a12a0309a4409c6da066d12e3fe4ab122dd715fec102272ecdf26967644a1a02531fe4a010431510f0fbba260cf3a37872276a8800f4e78d79d9da4ac24826f694794cd0bd5872d1ec9f825ad3e0dcde09235153ab635a76d2bb94e78797b8071388c38f07e71b226ff478ababa5e8410cca0f8a039592624303b0341385527cf29cf1c75022c63414f55e3bdc68a333a76c4b175f4fe41f68f99163e7d17bfa8867bf5d8d966d09d4c969c1ef35667fc39f41e99296845ad7a3e3d22796edd2c5e2086f26c08bc780316cee830cdcebdff103b26e42d867b8defcd0d770174d85209a0d82ec6111f88db840c41af4be3a826e98a801c69c8cc914be62b3bb9a7cec0b0bf90275b1a32f58851044612f1286ed90dcac68b328509e9adfcbe552a2299bfd7e47033d99838572cf39a54e540565b8128fb4f5e6c5474d28bd9aabb6c277ed445f67df481a6758d7206173eef1c3e49e4ff85e58d5160374ad4d4345ee07bb85cbc7b74f4a7267171843cf641af7a196e63a93aa197f0f8539068b5efeff32e42b98d081196d936739fc79c32475856f3c57a0f5d5e6ba86fab5442e4680d902c124a20a48c799fa3ec84b7508399c3257ee8db20212fb9520c76288ee94906deb7b6945f310b87c5f86004229312e1a5af88f7a3ef440a2abb7d38e5772f5d01a9ef170495c6606c6eb272e7a6820926deb753b642ded3658e444f2c70e894304d58121ab5bcad54842a6310e4c7020b4ec1f9d39fdabea0084da0e9b2727e1904a2f15bf0bfad2764047fe63687fd0d94f4a352e4007dad7ee0544fd3af877c791b707311882d39bd6daa7b21481a926eca41d4d56b545a7e420792ff739be4a10672d0ed1274f7fecb71e2869efdb94fef77b6addb1c061c8d5d76dbcf2e362f483d15e46420dd8de483164225da5578d7986de9b7fc83daf6a88eba7de520ae45fdbf20fd90c6e339637c6822a40c28f268d804db3d18b37961d5ae954cd71c1b98538643d133ed28517905af0780064d7b8822a8ccde83e5b44230bcc7c11127e145ec5381947989c782c961e472f7079912ab7503beec72dbc357ec2b5a0510c9969b4fa3b8dc0b5b814690da19a9a2fd5e0ed75745d00beddf7af2beb8e7db0b823f41975296dd22369bc77cb6d1dbd30a5cba2c1da48af9d0c556fec48446b6985f1a4a4433fb45e99eb3043fe7383f1b48413ca7ce62038d1ae2ef0eff97d9048dd05222b7ac54841c362677db56f3d2a1d56b2d952c5e639e6ff3f921f00d6ce2d8db2e3d60d565ef9300015f994a465971f73340db2e3e58d22c96329bd094bcd879a110e38903730a9df2a07bfe6d4c7f7279b8463749966ef2dd250adca2a61021efb05388c65634194b262c9dddd3ef79bec76c4cd6baf28de2618097b82b7586b9d302a48628bff8c40469c8645cefa0e845c59835c27d604069a84dabf53651acc31805b4bc56fdf210dc3292f09477f083157e581d3d48c3a47b99a4e34e1026491e26ca6915dabe4f954d7276272ed6c051ae68e1be889a7dfca75fe7e9a8c9f5307ed6b19968e9c9263e9c0d4c34e4336aa63e3da044643e97b5f0f54b99ceacb730bda269a9cd829ba5859cb636a4c6e08e727f54dea290e7f612a7ba1e45a6c829e86c8a8d451d7873dc6bfc14e5c57b5a1068ab929db87ff1992dd59c10d59c9cf3d1e65f9a216af9c648f381b3c0dfc8dbf1f847d8b1ed05015fb84fdbb876aacdc3f27a7ef8e6d90f7b96935820fb3af24aed04dab0f6157356ac15407e9cd60989c1963a8f0979420d673dd5a33092965a1d8e0b574ed5fd8f9fe0b83cf4d1de5b6e3d01e0c311bb3c37ffa7b0158b49fd807c667c1ef1637e2c28d6150b42947c73e72ef5eae674671dca3c1bd53d188569c9fbd7645098eb8187c2f43a3cc991193df20ae10fb350c300a3976c64a6100fa4dfe5563acd74ec0046da590802612d0a2f9b7123569485b65106c580124698cbcf6c0c9bce505d7ef6a31fcdb419a8b5b2345b9e61cde3071b162cbdb3fb7e2031bc244cec61dc8bd9967c1d49dc30f5aad107a947c9de8205ceca534fd8a750ebd08f92c2ded278d4d8112ec43925221b2c4f48efce46c5fee9ed5d5511ebb9bc9943eed6e9d27a3878fe109a6349f31f515ac4e5f7dd401c9f75d4f695de8732f7836012122060efe0e43ea947f0606495daab8ce43504392d82366260cdd5a3474d05975d7f1c2a1adde98c478caee481354b8e4439a296a269d1492b8f20f077c862ada44b1bcbf44e23ec862fff88c153699cc5384e7ae3a4640ac0953fbf4ff07c35b4ecafa431f079e70bfaaf1d130365a7871766eb2be13a645523242ee698735ce3785e9ea9a5a60de209b96e763fbabbfd98377f0065ea9248ab43548dfc41b8d0cb58df7ac6974507adc9e12d48444ff0c51407e004c28394288058815915f88a464b00db0d5db2c0ce87f9fff7b06761ffd4cffb5984bd775c1025eb28766d3fc1d9dc2e9bd7f8ce6202cc5405060702e82c15aa9084eea31b78f02cf406e16bbb40ded54d299a9011099cefc3a9b8d420cbbf77f6053b0a10829ff14be5c17adf5b0a3b9a77d53a2b5f5353a3193574ac70ab3e1983900971ccbb155e8929edcade951fb38467fb26cdcdae1eed6751eb18f69dad13b1329677b63a68f331a7266e87dfe7be5a933b8267f6eed7f5f4db5500571220ee5d6326e7bdd07c8778fe02ccc30eb1baa5297c019949c96cca62767d2d829dbe712dade629420f1008215f592aee25dd609611611fe0496c7e026fc27aa354c77302880c58e4bb90e3205dc2b5be77e5be975ca67277827e98753dbf8b9eb853bf87c3c4ae640c2e32dce06b8b3e6f5508290c3e0a723e9a28bc472077eb286397bf536fe7e8169e632e5bdaeded0aa73ae659f91aaa2efc25eaf9c379f5dfb77bfefe025aa36ca3cbe2099c6cb5121670470edbbd2c4635ca277888377947919fe43a3a9ccad3bc56c5a1c37b215b4fbe7f0a4d0a8d6f1b5809a7fd11951bb7494abb0310632c772f74c3026ffad5113a12b8d803c89db34a1ddd7be9aca320e4712f241960e169f334076d8fe44af13999482fd3627ea19965080dde6d71ed3b3c673ce771c4a174ffc425e85355370378f5d511e801c9336ccb686917bebe6a46ed08605d6c2b38516b045da657b3cac99453880cce554fb48c7b1ff726dce9a5cb42b61d72790fdb2ca4c464e247197a4e5160253b36f0396bce92b93ed4a9531828d8790eedde2a8ee46bc9867b427a8295336e487024ef3bce689a916815255e3795d948decff0c6cf4dff5feb10e248c27841db1ec27e6f5ef0c94bfd8fad3e051f3dd21c15a1c066c1fe5e123bc8b4f6082245c66e8fea37696cb3fcbaa40edb72f7f940867c2efe3b9026189a914d6d8e840ca2d1cb5f34aa09b10384192520b7ddc5190fc991110a095f4fc7a53c7972cddfc4c3ba908f804e1ca4d925a8cf33e36b770207b27cb011f2c183d9c0721a9f9b3275e37d567ccd3b9b86be7799f6d58108dd45ee9b62673461ea6ab3c92bff3fe5a598c1d044a4d8a60c0538f3dcaaa4e58ac43fd6b96e7ce7eff8ff20a27d11b170330f031c510e3db9a212edb039f6943c7de6e8fc9083d6cec60b288f81971cf89bdbcdeb40a0ffd2463349f0c1112a65ae3c16bfa2c716864b0f6ed05e4dd3572a01b5ef6c63ed8f2d58a3a6eb7ac0bf1f2b8725b5a66d59ac2a537b7cd1e1f6496fa354629476ccaee507d240ab813d5f21b669d31e6051d2f44b3b2b6cb1bbd70186c00a8d48be5fde91a8edefb92333ea6a1d59b38af693d49f2bebaae11fdb477292156a3212053ebfa6b724b177f97429f92b526ccbac08d610d816ac01167309e365681074d2a3294feaebba255347e3630b5f48cc84035d519101582dc32fe44bc9c24d8963e57ca3e231e31044c7409722c58354a6ba34240ee4626b0a61629e56285baf0270257c1219fdab8c360c59c6a11316f9ce3596c7bd870da2d9592068e56b8dcfa300e0d78da758a5712f148707df95e4a1100b8112385b23d299c22b06490de98268971a421adb5536f0ba8ce518790fd686aed7dea359c2fa9f86ae0438a432afddf42708d4a882b9e011ef9464196a3793dd0fd6cdd5807666d74dcb297c2f857ec2ab080be9fab4fb507d97b93ba385acdff67fa15c49789d0c47c325a57729113782584078ea2da14621a7ec39be938ee3e9ee019c4534e2ab6a0a02808f27211bfe87663dfdb4ffbd19363c6b5f36f8a6cb5bc7e7a30c45126bc5b170835f27e57c8705deb1048e52afa95dd451d10b1ba3ffb3eca079bea96c517481aa093022c365bb99a24655d4f5f18915ad19264b98f864a9e7ddc73b48279ec45e681b88f9c96c9c0f0413d92192561dd700a52945b2693fc8f0a1b33bd915dce001599a6ce8fdfb7898a17db8d0238ae5e5c1d21d0b226c79dad7a555c9d679287c5b5674f02bb08fd5f2ffe2bb1a426684d17c39a14472ebea9b4f1b63f75773dedb073d0d72d54c6d23a1412dc25a52ad1313ed9512b110840b7a1b0b030be3fc8d4f7ecfd79336cdebcba3220af6afa6e1d8e46d45a5ff673a6536fa9b0375687c652f5f7ec70101c417b334ad4156d469eb22f0a8c5036b66f7db7024bcf1f361c9caf11e0ac8bfb6dfcdc54b4f6d11e1c6bb4a5be4cef21f3f114bd4ae20752ec4ffbaad09cc7853310c1cc826ba823b2569498f1cebc744a7120f74ea957e5fa76a07fe0959ce471cfba3a8fc2485738e9f21a4bbf7c23ada2c16ce2703262cfd1232a45d1b8c6dcedad2d52c9bfdb8bbb76f9858e1e10c4775ab5d4d70741146ea18d5c9812cb90bb8517047483266d6fb6e86a8c6a622866c91fb7ad947453547558c24cf03fb6456ea380c85413912be5b312739f0bda419ba1aef40d1d16438f0fade02f921613fc268ab82c659a9fd202427da18838a902e24dad8c0f99683ef3bb8cfa2e7bcbb21ac5dfed14f904944f9e1168e729fce6c45ccb8b9f2522b16c8f1d9876c3730b019aa373dceae0cb1e3cf062cff54164ac3d6c580c191d8c3ca749240d0f239028e529808645c154f1b172c647ccf981f80e1e4a7a2f1c3c1102118a1864a2e4399bb49fda0ab6b409a1f1fe91403d29b14e2b5b27b8ca4f9ae2df37c4fddc1347625d234e51363f2bc4ae8cb0502d3d635e90cea6edb1b9e8305c0cf7e09459d69d117c582d708658f42abb8ce7c663e04c1cf2117cdeb57df6384e5a9e7361543d49cc6658e59ac359a31981bade834a36e14f2e9c3e02c9908bb0136586da86b0c8d3e2b86417c6fb370c45859829b5d673b5881f27f0ac2dba08534891de92e444d6cb901a5dab3e7b35cc8a62aedcbaa18fe7c79edac65568595984a6e57093df74c4016c25fefa882922c8ad5c02fc3cd894ff1707bcc65f1267948ba5c3e9dc9f257f5d6a390373bcf745faf9f2c9dbef0ca59b1f65a5c16f96611f3ca627966255ce449f5fa781e3ce37302eeba097f9cf4cac6fedab1a0ef16f3ab078d8249e3e6d5ddf611e5ed30641b4083f3604a9ebdcc76d8d00755d0a9a9df7aef1c4ce5c147eafb7aaf7c4da7c4eed6239a790012c02e80fe00da648dfa79d5efce87b1944ae329bc5120da93da7842a6745d790f62cae1e42031d353ed0c0b134ebe7d90be297b6039e750da5af1ea98e1068a64cec36184a3fb8e019c6e85da93465b854f940abbd463aeadc56dd37e908a278c2ee1903b7cb8b96866e66d42c31897b79bc543cb73277f6cdd3b43b89f9ad849124a2dd7c0b360fc9d9b3624e0694d4229a742ec9fc9d5b2c149d7d500b36ed000dfdbeee2bd55c63fec9d37878678cda321da96cb538eb14f4a2855f9a5fcee2ff85a27a924deda7bfa20f9de338c009f2e5b86b0a600802b2b098c91c416c286232da063e9285be9c9f94ef42c0edb70811ba202d2f52b091d3a7eee8fb002f2462dee7fcd04bff3b942c69ab4ec67ec8dc42a273d2b3dcda0ba534ccd23c95032e9d648213162df63e2a0567379836cf488855c7f2510d7bd8f0bec23fcefca5fb2890200037e172ab33908aebf7866342bb6e8e52565eb1cd29f1809e70fbd9d258a6ef7c42a77ce7ec4a4bbb81df67b3eba2cf3434dc4cce4a2d04f342d6ad967ac5df5b3561b312696849ab2a065030f2d8e8b58daaa6829d7f168fe53c36b8052063df3912d1098b61b464e9aea4ac2843bb1597680ce70f440f46dc2bc34114cdfcb22b67ad15f4b6ef27d58b4c24750eeb6a76b078190ba98ab2ee291d5ea2870a507d0cf858550e374ca85d04e17b7a9af27937035467acb377499748e3c2cd86b21282226b51acc58f6242eb295cc3be2708e96243aa909f4369b489f9f002f74b85bfd3ae48ac86d470d96607a55bed77953d4b469eaac56a064720940bd1e052191027aad24073f5a38b9cba19c5c41906405e57b1e7c747985f21cabd9002b7ce5793595276d0f5789c15f9a33b7317bedc1e91aed152b52082ed8d7687e7d311e6f82452fb85878e835415ee165aae4f05b0452568ab5cb12068965fb1325ceae791cb38e4ebddbfe7ff1f8af8c7698f318cbeb46ac91971e22ac9849fd56936b78be91d02cca869941aebf16e8c2a25275a60f811de5a147d0e2026f45900f01660dac4fd2439981b21f8a88e13cfcd059d305de397d77cee9615e996faa06d26b2680598bf58e287e5aca836789aad0a8762374a1cc0d1f89754189b39757ae17375b668e78b42551f71e0587f1859b495d00c8b79f2ee2ca9d8e8e3250310af9d428ab7fcd5fb7e47c17404c2c070044866c80cc53d3bbec9c8e4b5fa25b1793f97ed624ba97918f2de2aad622f8bef8fb7cb779498697b4a8fd2d629461b76aac96f0f9ddb310c700135e1e15e5e7458fd47fae2894201a567fdcdb7f34fa6fe1f7bf766e5a4826cff53e71c4916243bc0383aae9bb524579fad966450cf1b2e19a9d2cf9fc1d32a968c29e74494c773d28044954b3cf59b83f3d35e18d0d1e70bf8f13878db97ae3d9d699b403b737dafdf06a7c575ebe14620fc13190452636c58906de48139cc8173dd237ec1477a427fc61a03c6cd62348777d24b8ff84debb6581747077e5b31cccbbdd7ab0f150e7e32092dc4797e2ea04231e8a20d5ac663b9d66bafba45b8aba7a4448bb0c72819e1f93933748e3403fb320b9266f5087db1090e3b63b8461deb354939c021fdb2a5b93bac138ebf4e13bd918b17fd5e06ed42e4968ac30b2333ac664d10d8ead43e17767f7db810ca9d0104401ad3046649426afaf4d0bca321e431a92fb25347625f7169ed7e5f9540c57f6094d7508b7d039f990668a3a5fea2f993a68a7c6d1e8fc928c56418bf212b690c23371399778926537ee47861483d752d28812ae0d53fab93ac300407c6e4185e83c3beec98e08775ba445b4ec0212b8d4e5e180d250deed2d7c6fb71f87ab161d213e1ed162e83e3cb62d540decdaaf5e6245912d793e7915ff1b66568723a6c9cf79f1929db65d989fa6ecd118e01eedb5aa94b2d0f494fc5fc1f8edc336922cb5f6bfcae0e5ac3ddac7e67f536d87185e112bbca5eb97e9680b4a31d6306017627d48dca196b1ee21cedc2b751d2f39fb068be45d69a20f208c03fca35d8301b57d952b7bab3217525354a3d3146679d28522d62bb87977446ce0d2a0de08849c7a6a1bf064b70adc33b9c6fddd2f511d6fa00faab812d1f8b2a376da302494d1321407b104a148a831ec4492723e56871c2070cf0e22444b64167256a2a9b3c8093393df09e3924af5ff4075042ecafff7d40e34c07ec69aa7dbe6025cd7ed73bc0fdf7e251c8a5358a53a3a9df1cbe9e1f1fe1461874a955c75bf9cedc393c7a22ed29f4ce443dc745b35d797631fa885ad636a49035c966a505a6b3907be677992d0e6638e081dd7eb563897b745fb8ad0a68a1aa02d84d29cd38ea5f414ac5e94ff1a4978083c1bf79183d28d9ba988c25e8fd1f98f9736139ececfd1f4608a81a814d35d65e25e78d9f9697159237b0d78bb59242d87929c82643b63901104871db53a76d1cb7bcae065a32326d78b96171ec7e99a9d460636cffb55148e5d1f7f6051420d1dc049a604c336e449c5035fc89f1aca678f8afe02ba04a9d749d0f8adcda460795a96fccf3d709e5bc2a36bef2e5f2d8ef7eab75dea23c1ee41d42f1b3578c4ef76ba384b8fadea6f8256b263d8a824ead92949b258e0f488ff5b23a7ccf265258eef10ffbbd287cf8bc64732350170a9f50aab1f40aeabe97ac49989567d0ef0c08ef6506f8c45728e970df55b4d8d6ca778fe94f6ec1e9b7bb290b94d64440a60f47d0cdb0c456ff13f47cd5f9530f70c9a5686057a9251035e508ca5bc7e004a70259326ae9b5fb6c05b2b7a6760d69572f6d39ed1462e744f16fe8cbb98d033fbef01a65f4429e405cf37f616e1c5a7c0afb9b2bd1ef2fba02b8383c44ccbc4978d71b3dbfc3b2f0c4ba5fc4e05b17733f1032b3297f9c32a2d8df77ee795e3b2962fa64606f08c5ec95a6384498d87f49f44b0075c9b884e1a48378aed65456cab5767f8d2a20c23d5514a4a6e8656e45e4c5df881218b96aed8b7f44d808b991c41200b531c52dfb87c99d8ce3b4bfd46d4940f1bc58d0677b33a2c88a3f83c92fbbb5a922758476d824239c62884cf01ba7ebb575162b2f2b6ab102e91501d77d9a46ee37f0fc4d02f006baec35b44ea979f571a3ab1460a05eb634bbddb652a64d9ca75b0d01945597e74b4ddc62290b43b1f30953184e4967366f1ec61c7f372f70ba71f3e9f99599994fd41114e7fda11cfbcc270e42ad740888b53297a5a55baa1838709ceaa50af650a641dd41c4a48ff7c505bb00c2da6a53542037146c3a7b2318c6ee65471ec8915bd9dc51d5438d89ba12188167eea35fa94c28ca7655047f17c2b56abfa99530ecd3a32aa72c7c363451ce7ffa7bef700883aecc0d2a14de1816b83b6e6569c856bfdd06555dc5dc776d30a27f48f64c10a3c5607461c2e15f532dafc0640fea16e41d7e960f45f7c4c81af4ff284eccaf73b5885d2b421a84bd35c5761169d2a5783acb48516c96dfd9606de128817c52a84deea499f14646a2419a522447a70f7ce80647637ca26acc20a6b4a67486a7597982aa19786556af4615fda9d4095792476b135e8aca3b5fa839a4f3884c03aa5627f2c3ebc77586941e14b8e2ff1fcd1fc0a0d37f72ce23aea81102a0d85823d5ecf20d780a88f7798cfd2afcf628a1d654b332422f2c1aa07c6226f2646cef06f0fde5c68404996d24bb00eec32240f00e78c9604b36f5f269cac053c6f9374fc84c556608413d0ae0d9b4e897c1d3d16cd50d2e9aabdc49668843e87791da8883d7f069c4ae82c714ce6138222db070cc6d311b74c461a2ec180fa060eb1c7f49e9f9e5069c075ec37c8a07656ac048b190446a8d03cf6112222bce6b041a2838e472022d698e87db3ac07ea1c425a7a70d30ba0282aff805429d2b12d3cbb8621c69d24e51efbd610b2ec2227f0c6e92d22d8d345c4cc8af14906c9499e24c371f9c645d3c29ede5cb2a3cd2ef91a4d3fce7826eeb3c46e34d4cfe22bd65adcc4ca2a78c953517fc1b9b321c129f3b54181a42ce65992b897d612bdb135b7545147e2c719c9ceea59200412215923fc33f3c2775177e0fde73eb0e07600f0ad967915b154c726b62dd7bc965dc222d678c2130bb93a6341c626be611404fd7d96f5b1f1926d739db6b4179f3dfb767f4fdfd79a58b31288dfccb72e29a4bb973f4f236ed8319984693d0c8f2a4d36cfd44e758c2d2b31054cc4478949872c0fbb3d70d54f78000f4055d8fafb9cd59956170bc6cda619b5fcb47f43c1d9eaf6821571a6833dc1980f409b8ca3bd778c01dbdef8ecbbe0ab7a1ce92c2cc578bb0882846e5abe823ff961e4349f78fecf56b8e30e144727d08950c13bb4bf3c476dea5801e3d2db2531f60b16051f8743e0fc0cc0ad196c9ccf103f8e632c38dc937f97ccef43636a65b6852018fc1dcb006bbfa2ec1aed5fcee9ce3156b227811a127aa4cf37673d1e79854cf3d09222dda51988ebf02e0638fdde0cda4e0baa29718e94b18a9ce18c1c42cd0c3d5ae1e97657a831a592b813522c16052e7b2cc7ceb394a662d60c929964e0334457d887f8e96eecff6907773a98dc96ab16086773922ee9927542bad851f6e9181db3cd7850c055592b40cb924ee05caa400ed8f1e68e9de700ec949ba637b11497436d37749927a47673fef9e65ff24c0e5edd31b613daae3fa19c1a712e6439793feaa47eec47b339fd01fa33a6939e03abbddc2d5dcf6ae797063e260a51be9678f53e440d629c171d5599c4fbab769bc39c2d394c716f967fb72c5b503642e39342573f9e65cd1ee2f560d1c277ec0c936d7c88ec890c2bb81f40b8a56a12b3b12283f839c5ace314bdab853180b21241b373be368d9cc108a8c03784135bdb3f45553d2da3e7bd1fada68085e2afb1f71c4e97aaa2f4bae0acb5cb8102b2251d705262c9b59042c6bd867f3f7e52f6e2570a2a7b5d8094025763bd7dc6b52420f484a4d774bbcf20939a21b5897f49a9f4fc440550d7aba2b93542d9449c8d8fdcdd9575334142459e4d87716f4b3b83fecfd87c37b3ef4a79b125b1183f3f7f3b684c71fd40a0a27ff65693093f06669b26d159f7f2d3beeb79fe2c739d350ae7cf819cab7ac824ba73e70a65482362a7125e29bfb7f463b4d160317445dde19115e5458553c0b1ea74d840826835d739c65065fa4fc8206faf617b8f86bb6a389f9e76d23d7c75523e7ed6bd9e52af484dd7bf5e15ebb6eedf6d71441ab8ad77af2d533d0c8242c392edbe6e6aed1969e8a601ba60e6f807d3ed0c62b0e6353c6773bfdc8b924bad3572531fc4000b6e7d53e74eae7244cc5d3418d87b36d99886b1f7d63e3865906895b56aeb2cbdf302833dd39b3b0fd20af24f4ad278ca38ebf841ad3a3e9fe271457189b447b5637675414c70d88997e060dc1ac906deb0682d573ea119ef78499ea519593f220edd1277fb6ee1fc2fa50c5dece1eae69c7776b24376463ec95d82bd98451ad6e72f65901f7930820b07cef5a5e2350223811d857fc1eea365654ae7849b5e4d05d4ea350a71383b000df822b403db30fc323de5f1efeace2965f5609c65a0de27323aad1e5961a2a46f892e6d478a3ec93b5176f4debafcdd3e0698a80f23070356f405341e1e077758382ea44fd555883377427da22cd01ef42a28fc8ad76d18e8417d61b8c16ea991d3b4d4c9dba4702105b02ec12327ff6869a739fdb97e212713dbfdfd9e844bd3f951abbb7413bb057183f6a419bfc6a0118624545e65c1e7928d25ee274ce2890665ffaeb24a9bd1de0cdd7c545a3072ce061b3f5f5cef399c550c3e4b3b32b15f2e49d6abec42144d36b8898518cc9f4f6c4a39174a606f7370286210224eccb0ba915eb927159c2f2f41d2442fe2dc4f39c0c908b81fa940e93c4ffe2f78de5ef4c9d472c8aacbe7991560215d81a10a5bc081855bd5ee4805bcb8aeb18fbe7170e6f43fa692de07643bae5dcdf4ef606fc66caf59dd4c5a030d268970a9c10ecbd31c32cd1b4cd4e6143b75e6f3fc755f617e7037d942f8679c67e07d2c4b9157a59aebc035cbdc3427573a3315a046dd8b4047b6ee768a84e6d39f6e60c2672528ce00f1738dcf1f60d3b9121e93abb7411a7e88508f65b4cb813355229875fc9ec64b7ba02c577da1814cf434ac0cf35ee4a7431423fe49107fdd1fdf7dcab68fdd52563de33179a51f7fd9d4eef4a934e942d99bac35d2c1a53b66a2b3aa0a000ac7b82714637066a2ae3933d2d795a2d4496496fd15e0809242f4600f276008cf3cccf874af8ac594faddcb4563416f361eef9f774e61f22837d74e565c26e104d63f97ae3b471f963b5086a212d064b61ecb5835e2b76c553d3754c46495b2d8b8abebb0d304170e399dd720007c4117ad6e9f7216c6f012a260cea52aad19a4c7668c2fba0ea3543b11301f7edc8606dbfaaf8e4f0c8edcc07f0edc71ab30f8314316e59c4a6b6ac9c68cfaf3b59ac063a3cfbb0e28927bba4324c3593694fffd31a8b32867085553e4ffd9003a89d1b873fecdc216872144921596c06ddb5f7d675ae8dd85bb1b4e27a720a9c750e44f47b28a7601a7e083e2f73d562836957821925d080f376991f7e7ba543990c23047e99c15b3d8ee414148356b3f4ab692eece940d145663946272f0a347f64607375a54b447f1d3d6c6eaa30e0e6c5d30dd2419d43a538748d088b0b5a426811c9a46a9745425516d60d77f7b72102bf8f331634b5daae96b71fd80996c7a56c0cd9f88fa2204a8be11b4952c7c1e6ef79dc40207ca19b2ed418d7bd694f6218cd5bfa90775e01090425543f76811e01a3c3abd69edc2f0f5e13a12a4ed29ea85f2dac57e21aad010693fa84380ae8f68e056f21f241100f8b2f13e7e723d1db1cb70295a81e882eb53c5db1fcbc2ed06a74be10629b6e34e3b1dccad4ed600989d075b61946e9147956140d0c6e5be7c1db695ea6e6da44a293468262ed76fb6a1b6d06ec264f63a856245c8c1b3bb04d4855ba05632d1df718f2c65bc5cdb9dee05f6aa612bb28691c2f6c29f802864714c20f9ebd9bfbb1a694f9df40c0b98f578e33eb63c1066d5be6426ea56129ce54fae63a323b5b5fff351c206a72e93bb3b1cf88d507406ef11c42f0df44cf8749992a1c9b4b683abc438357fe46d35349288caf8b175fb043814fe50ce246221b5d7742d32b10d943438c72255fc39019ecd6cfadce6b998ee8ebde7838d715738adcd97a10a1256bf1ed6eaecbfd03905163e7dc36c0329553459c6d5c727bfc2ab9e66a0610b62bb2671859da26c5739379789df2cc4c6895b4644fd9b85186ed3d3b085e0a7c24cb1559e72dcb7db341d5f93f164512b7ccb6504f4b2641e0636215ea26d4aa88e9d896da44d3a789247f326bb3fe097aec2e9bb7e662e748fcd9fa101ece4aabec083ff0352c966ab0eb75543f2d74ab01ac8b63a00d5061b6fb68e9966bd17b9ac551f0d3d474e8f8a2f6e71d485d0ccb2dad2ad69841b2be6837b54e7c0d029c0f20d90edbafbd21fe7a06cd1d33c0f17c770354f2e7f4d31ff9c0fdf6741a63fbe3a45252fcf9da9caa8b6cbcb8de023782f38e29008dee1e04c19b3ace2ddb325d9949f3b5c2673b8b82ff82a778b6bc05950d141b8112629a52edc7d09c59bccd9c43668cba13e388fe62a8782499d0f86c6a096c5df2ed0a362059df63370a0a3e497ed02f425774e4cd2501871916637f0c00e49d2ba024d80f6756a752c7fab3f7ecbce77b9006c8a8270c9aef093c071fe5eeaad8ee134db2b810f1641f6583e30e6fecbd19fdd40c25f36ee78c1c18db6e7642d2836868cff8773362b7e4ec1d3d11e363f0904bcc68957808370c262f3276133d7887b9b774a43588f50af94fec1559c51631e4d9d39c126622343c576f13168bd06a3838b7112ed551c4bcd870169718fdbd3f6c4a3d352bf4bc62cc4a0ef94235541e996b102812e7e2e4f5bd5ea5cd6617263b53a57034ee1ec68b9ce25daede8e7af4a0b8f0534715a5e090f774672fd4a54352f9aa27c439047ed75a0bfccaf610d9923a51fc564944e31a87a92f025b26e392cc0cdf0210628ac5242aa031e58645262288ecc300dc0c93af1b443424cd198ee80fe0817be8559f042310b82291518e5ba661f97c5f94414b2193dfacaa9866036fa6874b2a922d49c54d152f01ccd2cefafff01d8a5d4df6e539b03361b9ec657d42da4c6866b84ae8cc6939c84dcbc145a5854001c5867e34f4d92b10c6c316121e2c73ff4214d20d60c5420704199d98dbfb5943bf44d18b0cda34a04d244f5bdefd62033e63d730558bcd1408bd7f8c13532a03e0ab1ff9685c46a92b7a7ab0cdeff2ee268f0557dae0912aeffe3c6ccd991ff1d1a7bac88fc341a7ea8fee75d5655142885e4d652c7ad3ed7aac65f64e095bc69c9147945292c72a81e89c0c11ed1010198e27913a413358f484992bd593260a2bbcd66f04a26ce750ebc9006feccc1cd53dfd982157e41d6c9b7653a7ae14fa022762a248fcb2f55e4f88871370eb64318905dd6a15513a8f608fa960a0e13585264b74ab5ac3748364954c98cf70de99898e74766ac90a07c73270100df9e1b14479a7e8a9cd35524f88610888e435bc74b0840357a42e3495d0914907006d21c28ff1b4cd2749443e628c682ad9e91c59311fd5f456ae003f7d66aeefc0779ca1b0bc5a8efff960611bc29101c69216141a92968e66f2222aceafc1a0fd304908b2ed01fcd040e4f627b66670119b095dadc2c77026719c9e7058ff9d020170c551cb50f2e4517ed71f4a0cab936dda8a48ac235cf504b4fd1bad7c291ecad5bcc53bf0e79bd66f7a948680cddc533511d978d61a32edb3bf00caeb6098cfe19df2e914f5cd2fa7ee05326443c9b64a2f30cc6aabd2578a24c7839372cbfdc9d839685daad418218069044c2aeb6634a3a35c1ff33080afec930fdfaf3a59b19474d2ecff73af68b87f2d6c0134be02c54f933439814b1f175b4dffed7ff17abaa046916cc70fc9dfa8fedd94b3d0afec416a14990d6300d599ad52e10a92d2849218d4b3549c56275cca0ee721e229a2eb0c662592a7ee8b97f95fefc410784a4c985c83522a247e408bff1f46f13e44011ac3b54e9804b73caf9d7ed7d9f600ebfb603e3f6c054c054105f45c9f3bf73e07ce9ecfc7cb812642de4d9ca5280d954b8d3af7ce8d2a1f66c10c3aded8b8fbb2c260f2f04bdb0ba0fa3a563b2800aa758209827fd3e7a137c1c9160cd6d2008f2cb02d7e0665d9ff0cf934f7e8d5d0962227612877af7d18064d5a7eea34d6d3b153c9ce4fd7b49443bfda11c27dde32c40f6022c4509d4e1fa7d9cf0d9afd88b4bd933481ec36975d39d755bca1284b5a231cbba646468b35df57f84dc6d4a5e4f6d338d507d9abe8e287bf2f6aab058f67fb161e1bad280cf4b6831fea7df081dd47c4f117b1c710d81bcc5a37b123d1933a43bbba067fa59e1ad01a446656ccaea625910e99360219333bd387dd189e485f205bf12bca5359248f080639ba9c88d3db243ce0adbe39fdfa85553876837ad88a737a5e7ea13afb9ec79ea49034ac22813f102466d5972c832ae9ef6a48a5f7cdb1917e191e30dd61e572ce930edb5ec129e29ba2ca7b816b94231c9cd55ac18e0946953b83180edbe22c620956ec4a50075047f65765b1e04dcbfd6adacfd0d6f5b4da30cc9698f1c958d35dbe0635e2adbfecc4bd656fa579633954278a1dbe74e03a8640587c619efb092683a2455b65927cbd091967dbabfa2b73775fb989bbd0a70c9209721b1ba575d9784c8e68d1bbd90a2dc1baeb417382cfd8f2470e7e27ffab941c9a0cd8c2a63714ddc089e0aa830ead2c5026dbffaff5535ae152f818b5a05d6a6f2c06c103223b6f8135eadabbb3936756a3d00279f3e2957f47441e9c44dc0240ddcdda1cd60c49e2797b636ee51a3d7f841b55563de41807030f62925b1be16d1a58d797ffcfdb32a32594aae0facc40b36ae3dc9a2f94dd2ab410bdde206c579deb574d7450d6ad8cdcab7ab7ddf291dba8986ec5a141d96754d460a0178cecb2f0c3a8f3c540cb24707984adf3eec5de4085d1a1d5201152afb7b7869a27df670fff1067f9ea7dfa03a222e815e50542f5137a9c8cf8e7daa716043c39ff6b49b7bc023a3acfad749cfdf90d7a5a93d98080435293c3435708b51547abe156a29e7a61e298a74ba0f80ce23a8fa3c6cb357561a9bc6b1c9d9d02070b1734cc3e64a393a1f638c3d81f536598aa9018a7645266266a00cec863eccb1934bfb6a5f52d9ee1625bbb016a533032b05ac25a42b19e4074817820a7ec4cf2d954a0d12272feccc4c1f12a80ef3fc99b95e4ec13c3d2515e2b6d277c36c44a99ffb10fdcdaee1b1f5ede2d742c662bf6f554d4cb2473ce72f49ea283e872c370dfd238a3b8ae5ac9dd92feff817f456e76a22aa674acb846dbee20dd8b5b96073431829fc2538a601209c19c2c89bdb4d9bfc54c8933bde0a93d43f9a90dcab59144c49e99b5f3abab527f62a1d970eda83bda5419673678efbe8681fd1049521a9478f901f91aaa53eb9c9f9714d921768888ff99042447b47726930440c0a57cb1bf3cc8ad04429cf97d970744e2b0e8c8940881c2b7c660e922939b1791e43c9cfdef1b3357edf3dd8683866829b2422c923311bee46fecc53bf2f924cefe5636721b0a2fff04308f15dc9d19c163b13671ef961ab4018244ad4bac60a62500ed328de521900458d231f7ab2b69d8f134a025c417e702c92071953561fd811779f0799295848ac6be040617930e5d9e60b69145648844606730df92e502f4d252d1334bc6ad083b5d511ee2c9ee7e58064e72ec1879cca61546c5d3d2acc3ff34bdbcd360d6bc029f6de1d39044a9d51ad05285ba8eb788f69fd5adb2f075254758365fd131e7143b4d531a3ed678789a96f8e782d06da516b426ebc26fbf78817493d0bc5a87ac14939737a82f87f57f323c7829ed4b499c13d6c128e096cc74bb1c275940d558829ed7e16c75af3fccd47c43d99f89b957af2a744ac7e3919759f7c5bfcb9ff8d10f3969cff04591f6440aeab8b9f86de8dcfff7230241eeaf5e5fb40abb999b0220fcdd79346656905d51d3dd3fae359646c861b0e30a4c86624ec773966b12d8733c0a9fc08e3ec7847e7f663e39f293b6b42156b136482bfcf43cdbe14df9ed9b847433b3a5709efc466b7414a9414875326f7e3a94ce3f589ab707e56c253ea1875649782f2f534a71e9e386b22af8ac5cef803743ba69beadaacd0c2bb94c0480c5f0535f2eb632d99e50fe7e32c44a2f779dbf89cfe8836599e128c1848fe0241b5555a5e91fefd04b37e6637130988dfa6cc2457d97ceec72ad5a8df045f04aa285523dcec7772afc5414e2d2850be68c0b796371f6b954959619ec7f039c4e99bbb18834aa818409d1865b92ae2ba133458000922e04f2bab21869f696022d2ec307b86fa05680c1f8b212d801782faefe2e5ed733cd30db94db2577ceea5834200a3832dc03502822553df4b19dc470e37596aa2e4cf5cc922d07cb5e77f73882716ec2cf28baf3dc0d51e48f760b8fb8bb2ef6547304fb3266128f72d3c04a264489be1da9e439756ef2831be463176fee2ff7c52818be821aae4bbd0ad8155cbb8338d2b5bcc8f6a9c4b850ea195e44bab04bb5af8f2fafcc2463e83ff7c46288ed42438d0cd29996f65bf152400bb8afc844dedf7b034ca5bc2b31a957f197ebebd738d6903ed4bb1defca9a15df6de883d3bb4b9b83728270db8c189257ca03a2c816f78800c562aabb70388a6fe943ce4ca8d9acaf1def0ec52930521a3c365f0a66488d8c9e3515fd3e49f9bc26b481858416a576b603e29260355a1b98b8531f439f771ada62bf3f60b32a9b215c8b9bae7ea1578e318eed2636d44be585ac39eeea6488311af1b299616493b38ba8fcc26af42d4495a2f972b9f0bceb4b63bc902705db432c5d5cf2b220574e88a56e8c8b00acf9390421eede33bdba12b8c0af64b83f04216404ba85b7fdb9c8ef181527b91bd039f32ba05a0aa06048068673e33ae1415c37b4540ce1a4c7a771f6514bb864daf0d1ad9938aa7147ff2a23780ff96af29c3aa21f6156d418f67bbd21afbb08be1fb1adbe28bc07914d811695868decf203749486758f33f1ed17b23d4b1207cf03b04da2786895f32bd13aad41389fe446173c2d2230c7808a5304abb90e05f30bf9212c90228e872754f35e8a6f4aea83f32bd8f93d20ff00c7555ba21b5c64b7d0923ae1a045735ad620ce02a014910196540ec261856e3d818e42699a2ab6e4b153387c400d4740e4c96cc389599fc6d04783a81028e0f48ce8320339bd543d8694f27c38fc4b959a0e811a4735d0549c15645dfece70e00c3771aa7eac13c77e1ce48b1b9f641f782a68e3fe8b5a484432a5782327b78780160208fffaf4a9f66af15bc558e85b318e1f3d8b5eedc3d74d3b1e4c4ccac01dea6d1a9c87c0463e17823c208f64ccc549d32ea68915b20f4ee6dea75fc534233179f3d7fb8397ede26ea261c50a544a73d59ad7e811e66d0d19894e19d3469a415fd6dbea22f543f832ab4d20fd79762379781b1b69da6e9d9df7aec8a67ee2f5f2e21511a05f5310a390baa1e3047284f45db6c06a3861d5d1f3f7b263cffc572035fcc773652bb6a1b867ae7ff729a0999e6c05d0b879024a5f0047e9957db4b946634628c5d0366a6e110fa6940464d379d26082fe3e8365ff4272ffe4998ed715985965e43fe2d0031ee6714d3eff333d262c94758930d882b04452a2474286993362efb5970e01f818d982e39a894bdbc2b5431a8acbe2b7acfeb907561a9fe436d0ed4e7a593d98768f794a075d41fc35faf87d49371a6196f2421f629b1f6efa24a3d52ab5b11a99a9430da3fc87cb611dad1a0996dc1935e78606f484f626e1c6e083408be1b2b04caf050dad710c3a6b8b6d83e62b1857416fb889bcbf4d0e1eb7cf68badf74842b14532b36f98d75b11280965f1f7cfd579a0e128143a199d41b9fb60551f810e1cff3e4e5ee5032b8ffe72b61f184b1e6b224d9c39ad839059919ed666f2b31b3afddaae1a2e7c9f220e9679a4db1a28de8b97911c7cc32d61df6d4ac53a5aa0c99994978b5f0b3d64629b943dd944ad0d49b7b3c511acf4cd6afe304b46f3650455fa0cf69140f867d94388223a15e042d7aa0904d5851d38d99b31946cbd455dcdcec60c3adaa3b026010bf48944a1e8a7bfc86ba616b43eb99ef03f88177143331ae6e136dbcb4ea258fc355eb9ab676115403da409d0e888d04628c0a3ab948f621f4ac19994adfc84d9ad91894658ff66632a915b46f5b4dc57f50cb46c389f749ef71a7744a6b7b3377a376343abded0b290805ff2bbcc5639075b41e843aca03179e3b1d61c2a43fd909a27d0e479b8d248c786197da35d470dffebe415f7c0388ca6f4dd9a101448d70070d2beba04eb12321028a9423eb7eae3ff5d607e6842d13c270f31d6756dc93957166de4293c996b920a88cdb2b539cc9f32b7c6159fa5eda062af058ea4b40f66f1cab419aa18a1543bad2119d4ebb05e9e0cf0eadd6c7b4a329f8e3b28d2d083b979b43bba8a90d852a4f1b4aa1c9d930161c90503dcd557524cd33bc4cf802f882620927bc43883504432831500a95c2918a7523dc19224c0555006df69ac7d8d2600c89fdc80a41d229b066346e15f8d6f62bb7760c07063940c26602fce609c65bf142f191819a4b081a4f3c598bf2310868734e24887726329f35956dbb8a4767f153b4a430133a9d7786834eb33dd1ee0b95dc1d4f780e92af431c9027dd5b41d82dffc8ccda16745607b4ac635585858083805299b6a5da9c09bbdff9d547cafcd3afad26664ad877366f78b2069bc6faf847e6e05a6924b47253ac6673a92fe78a5fcd9428593e9c5bf1863bac158189a1944b265454099013c4744dab82d253819a5f474d92c35ea7378080962bfa4cdb9ec0b7156f1beadb93fdf08c85f0dc30bb5fa77fe26c7ba1471b6c4d15adc2bc346384a690373d2cb6d520a6661a80b050bc8e291d5d5ac405b485d385a7e6af88c87c4e650edcbbbdf24a6433ce7d293d32d618882ccf3d221fed6897fced64ad5def6bd16012a7a12f59a86b74d3d53c10dbf70818baa1ce0b9ead5e2755e589758cd2965a815ccf4e8f79e48204d41a7785d33f6d7921085e75e59870087f07cc45ccd31f2aaba61d1776028842714ee9a0c99a29d32d4b0816328e2766bbd614871d6df08075efaebc0c314027a86af11e33e1063e0d59339c21db5e122f2cbca1ea6ce35d5e67cf394c0bac10dda47ba0eb86ca49b284f9c1666bde0e8325d2527de0eb6348ac4c7303f153a48ab7de381f369797bbf3497196b434a96728788e7dd98f67778dd3cec104a287fdeced07ed010f5b21bc9f3571c51b3d3e6446fa499dffe86109508dc42d71a30279a9e169603e72cb225e7e1d9a2314952bd26ca9c45fb6593524d1ec60f4a7a183ef9448c6f2c20a9b9ff67e812a76653b9fe41d29b5da774897696d7b661b7f2ee4ecdcc13576df8b03aa515c02aa20d7a0219638901ecdb6f96dabca9a3a99db3d24d04691f0744ccb28a785d1e7314bdd6c3da10352d748c961c9fc5b6cf295d70ab99ad22255dd554018e444e480a1283d47b53af2481e7a1ae03986624befdaedddbd8cb14d9c81ab14f1d22f25d21942594e5416eab3dba6ca8e7a9a45364c5843cc47b878b6cb78d9c6abb8835297975635addbca07c5149a75390d07105fe6ce2bf22b8d97de0c2389bf1908421455f3b98c45313791c173ce26ba7fcc892e333424d995f2763a3ecaddd8a85400c9ba9f621afc16e1ed5b3cec2269e446ff0ddf672161c12769b784ca502a8fa4d12ee1590a01f657c9d5ca02218ae3bfb65484f23f5b3c2a49d7a884fa78fd3848e026ae94b677a245e33a08e5414e18b29d4b50d7fabe0aaee934e620f237bfe2fc7f98520ddd0caab5432c78c24888bd12c4e5d29b9eac3d2280ef59e07909a2a87c6139bf1c722a0d78831caac0abda44a1508aab161f095aa09c63b261de17a0b60d2e54d0c14e1fb495397cdc704e3e43356d4225e4d2f4033db4070f6e9fda25ba62782bfdc5b54732dfed39e8d89598d3e30d4f686e72822d1e50c2d7863fc75425c75e5de4e8bc1efcbf84f2dcf6c9d6a511295f7b1dd569f9cad016f264fe519c40345c80db7ede5c7ee556944357bb410880577915b26a6851af1b28a4f65ef0b013d60302098e85bd8fb054919595d9598e514f32144c4858eb5130d67987c5792d8320ced415333037be79918b626937935ea4f763804ae1690426c4879d57e986c6ff6833ee027f7bb47bbade27f6ad8c1f99026c35847ce630b44d4bd78395b9c4167a7c518fb4500489b4cf61307e79c6f06c2a6a77504c46217de5a5cf3c8cb6dea0d190e34d9aa7db94593fa58206ad31414672b5fc365eef13ebb6522835f72ac3fe7a34b41561119d7684e8657f72ef45ed559660bb43e584f009547f5e6d4fb479ea593a224cd719b7060640f0358e28d20e78246caf1792bfb566927980bdd96881990f9b3ca32b08f9f5e45b1d9de178572ac1013feb953ec2169ae05be8de8058a33d4ca002d93df43b3b1a025739a9b29555051a6e60421d4e355708f4f4b1171e477f56d6b1aca5c5d6d6c7a8080db816dee0e8bfd6b02b13edb8cedd525d31341901b79ef388aa4e3132d35552e7d30617e41037336f441cc8ebb67711a30ed549be125bce58e3efbb3f35e31723110dbdf5e4898d470a9271a9e45d29e59a456b267491db775829100dae6383a8cb3235a06d5f89b2561311d59e1558c4e4b74d29dce3d372a0561ed89404309c1d5a0ce06f861dc053408d875b72dc44e5001e637ceb9c2c59ed8f981a19cdb01957a7ef46cacec47e4708b20b2e6b82d61116778e2365e614ffcedbee79d32e690ebde364a4df80191595e745f4ba5f77a87a728aaac090157ba11fe58e50c8eabb3d71be7413078cf591f0e59dfaafe79001158abd0fd983352dcce8ed0c8db15bb0e94389f95efb8653832915e05668c283fbbc53cf84e1758f7d5b0b91ff055f23834714e51599a17c657b50fec5548bc61f647c3b01c97a8f58f7210a5231cd1148ac89651e6dfec2d6714f260e08ec657e455f3169b8eb9e433891bf0fd51a67d655f004dceb6d6e11e1d64513c9dd05d494b9024a9d80036b567bae97a681d2888d152e8b98e91ab1cc7308376cd18c97d9dbcede3ff01a421cec12a613f439d75852ac0a3dbc249b43fc7032e66d683b6a6996043f6fc618fd96906454615beea345b338d152305630cec96ebeefa30a56b5067551054528490b0eeae5239ea6923b280947a2eb21eed1b351d0948ffc84abf6cf0f88be968d6f91919380907a25fc8ca1df2d18795a95a2ce7b56e86e8a43bcb0ad57ddfbebb948e38309043f27875b472a5b1154494ef26547366841131f1fc3b77583e405b5aa47821d80e69cc108b1fa793faf0c93910588890bb16491fae8dc1f54e2e62be968277c08128f5c7d1d2131463bdf65114b99ad34cf919de4792ccd9634ede3bf2df7a01b341d3b806a591894b206cd572003d7ab75fd50d3581932dfd4338ff2e75eb15eb8c45f05f3952fc70dd68e9852fc80cf03dda5a89a3d6340597445b656d0290466d1be4d91c36f9e4b218604a3a53ab152111781698fdd373c236974bec8a461164268995efc894dc3e49df7c57ec6abd3c59fa2b761f032e9ae3da436e5b8c53fd36f08f2a25d37393e72fb5bc7c9e9377274ee02f9884c86c216b87563d0211520a8235e608a75b64f586eb7c6b00144229e26ffac52dd47d6677bce1f2b29d67cbc6389d475097801eef67a3946924b364267de8d386167587e9ab8698c81c5a1e0a8169c7714ddc5b1cf11dc15178326dce121cea7f9ddf1b17fd0aad52843d42fa7bcb0451b07231face2a10b6780736ed32a65dd9147e40ff10ff87eb8d412cd8fc92256dbf3e86c394366db7b367bb0bc4994961f2905959883bc6a118e527e4de25945c92f499d2786b2e7ba19e82393b9976fb45d159e31d79a26f0bb6f56c1ef63b1acdad5fcbbe36beb42de6f9dc09c9de78a9e3702fc769b33a228c47eac3bcd1528c90cfa0476091c4e0a323d026a367b82154f1293b31451fb04d98c64cd63507d974cb97184f0d9cc53f62d0e7df9e6dd528bc31c8b6c0f7866dba29892e52ae7bea0b9d3b6fed574c38bb2e8334058a620f24b64cf8234b628ea3292cc19d72a6052bc9f7cb680c5a128022b5e85742f7d7c5f0e8430653be78267e70a39d2ff7976194fd4455bb49e2845cb6b05958b2a59f8943224ab7b0d1a5c225c9be80a28320919b0dc0f9f30c6ad4cd1baca21197d2634b293bafd4cf469579e90ef57eaf233028581b7db3df4607577847df7b38ac452649740b3d9ec5cb54d4a49debc3bf7949aef91cc444472da556188a8eec11de03635b8fdc698b32c38143cf2de729b0a1bc50a777050db91d2c19546b85a3a846569ab3201da06574009c8e5c708dcd2ab122b978c4aa39973c0dbeac8051a8c6726be864206583b9669818d9cd76840d8b1d05b72150713e3c304d853a691535600156a3c3df9366e9f8b3cde5a7dc56ca3a30dbe288d4817b34e9e0e67d563305323c85d59249d62093ae5402bd0ed45e3dbf52a60174154a891721dcb781117a51ff0753ef3cce549c37482a13540d773f71576d10d67cd3e0ff5a25a3f15580eb9e8db044bfd910c94cb1cde5fbb5682a18e64a7aa7b79f636744835095d0ea695551ed9354bf77517fea0f506a7e43c7842cb6c63113ca90c1974509354a840e57129af3422f88e61c99f110dfe0701a120782fcd747779f0d130af31d89142c67a1eda4de6610aede25d61015e9b40571011339fd848172abfc60b3412f186bea66b3bc3bd4c4a4c8e97095eb229d41cc44f5a74efa2408591cdca1d543f03ce9dfc87b797a56f1c800fe34988b2643966f4122c0f57ab98d70f17a7f1b657f3047dfe47bfbef44d2521357ba60af3af0fba849c138b761b04b0fea54fc89cd912de4c8c45b0383fe0ed19faa5569a9a3150982bea8b3e56dfd51014e33f97729eff030c56334c80afcce50f1a021ffa61d4d99ad44fc515ec86d7563b9595cda96533745ebff050dc104d2b200b03ab10d1264f562ad42d7820f2444544a600a87195a809c79784a4caa35fe143ad6876312cbf5904c33b216229b57363bb80e6de91e7b0939c17f41183fc6aa9650458bc538d5801cd22a35a7efda7b4f084d46c83f404ee9e480260756ad0682b57daab3f9fcd38cc8289ad9b964e98e3c457ab587244868f1c83356986af92e11f3a773f95df5f7bf6dbcdd345ccc20aa3eec9762d3e0aced44aa062974a7a01cd4a9d6b25fad2527ff9bbbc8e2025d2de73d1d4edded903d38dce8ae5c404bdc5e0d348a3753daf017f381a63dca12aefac5ba90523a5832fd1349b2e49a26ed754aca67c733a5ecc05fa04963ced09c556ac1be678a418b54e4c985cf1e0dddeb3908ccf927656c0a4155c53209f4a5ebff36b3694a61f44ae60a007800561f87ae4f6c212c82a347b2846858718c21fc84b03cc2f24e16fd50e74842751bd5c766d8524d656fd42f979651fe1a89f0654d3b2636d0c72f413f5694f84b9bd2ca94c603fe992bd0a4cc8fc5e16553af49d3a97e24c03eb03837570da612e1026be498c6e9ef41b9eebd4a01971676279c7ae760f270c9e1fce1186448a7f073b734afe6711a8a2aaf9ba8eafcc873ab00637675a687b15aa0c1a688776f41c65e8a406bf6a3b67ad3ce117518b889a3d1d17d7ebab20fc5d89880f5e0cb79e3f81f1393681c68415de84f3a182ae42448d2047b9f2f1e266b88da038f490567f18eeb191eb1f756972c0d09554e6e8615b7931cd5c0867fcbbd8001d75f663b994249e7b25578156c6162e2f79c93a516b70ce505f99428481d08875d23eadffb323d08382c91d8996db4423618de46d0692cbed947a12b5b7845576f26f59101ee112dc58cfffff49671b11913ec5f575b112ae35258033452e143488a2b6227b78761b836e90c3ab4849774ae4581a001d3732eb405c152ba36a123ddbc6390db4cb87682aba059cbe698f5db384ff78b19561d8f81f7d41308f6e99593a4a6ab2d3a0992ff43d00634616b50927cf5066f27ec760ccac987e9060b35b2887c5dc2325f7c9e827cddf59e9ee54b84427c2ef4e589e1738e26961462e8e1339fe7d1b80386bf1af2e491383cc9d0d5e37890bbe7094b3131f05843ffe351b4b0874b10161b95066ccba7fb6932544f5baddfe89a1f8674920671fae50f0a229094f2f4d25c8d8f7df74f9c3bc91a7b3ed069474d9b80a6081cb0ee3580f159b94029ce4ab30ecbff615b012092a0b38151e140794f281061024182388fba07c5660cab0d2bffa136913d46aa1d75e9fb7823616656c3cf14cb342dd16e01e981eb461096a6e9cb5c02fea18179343b03764521f8e485de6dc08f13ebf13090ac6d28b042daf9c4336ef96fafe1ddb61eac54ba21e3df2eb8ebdbebc6a0c1aa6d0f020fb2d5a07aa285932862b23de8f52cbb9cc994bd18de246987ce7aba1f71dbabe2ff3f77e51d4721f5ee48e04d6d7e8742ac665bf0d70500ccb20665581007c61ce77d15fd49479a4b7c0cf3cd177bb409d37e715f44c1b4ffc48a365a5ece48585218783adf4eefd66f9f6b976f65e1e9fb2661a033244236250fcaf45b0d38b984b0866f2290ad774b3ab619e0f7b84df2724781fe8fbaa7d8d4bb721b1f597ab92cf60cd94f8453d895d6108933bf47e7532a567f37d62ee7255a1433e2dc74c921b044b7435cd2ca1f0854e2cf4e0d044520da71345a846cd9ac4413b69fb7dd733f1cd7aa24d0eb66808c475122d8af2d9993f6718d8b69dd2e375671072bd282175fefddba9add2152f34b67e1d2481bc24c8b3a471aedb3648ee2f2084f0b02558a3f51ec58dcf8b32c5a64d01cd93fbe270c3614fd64d594e1974429aae653945c891508c1c4291c0f9924991138c3d370fd772486ae21a09a233060d42f5052f2cbcedb4d1687d36a92b067de2cbd1f7c27b115cea7103462a543b3c31e7950887bc9d7103b8228e40f88d4f9d8810374958464647cdea10f4ce4d1f7290858f084ba2c526e24ad80192849f6a5df51768b189d60729a189915e78babd8e2353910cce29cfeb5ce67af44365c24de30571efdaba631a59acfe089bf3843274e8554d74168d10e226bdbee200e9c4c1e4e728307ce16eeffb9f81ea7d2640a3b4c76ed8cd017b920aa29384e64c1001a550132d349120751184be4c5d72a7ac5c72204826f4651d1519cf0ca848e4ef86aa35eca51d5f8b6ceda1f0f4813ceee7396ef8f28126f1e6ae7f4eb47f622e544c5ce04bba204398da27293c9e8582bddc250afb859c1089af1e34cd757d4f6fb710bffad7758f25406d0c04e238f56ce2c34e6245063360c6a4df9084a0665d65ca835f1cee87c93f5566fce80d59ee326ce4fd02005f9a1f3c03353a8ba3ecf8dff86cbc5b366522a1b366ac0548b966e30907224222c238638696476c39e3fc80c13a5e6ace4e1fbf789c70da9ee19b35d7e84784b6488723b550c90121a2c530e79b584ebbd9b7b3286a782d108f0d9e493c48d2f04385a3c94894d76f4d966b00d45a98eff0b50e6d550c04ece9dd7787329226a82be931210b7e038a8cdf6f0ee186abfa8759b342db8ecb5c3d88072584182e0e15d7f8cb1f7b1cf57c06c095ec05d52c5ba6d82f29d08422292d7207ecf4c7277aea82ab36db0e3e9daa6411eaa06139e753f40f5d9c5c0f144f9e7845170baa0f30772a7705f250c79e7fcd6310728a7f7b3ee94026c623abfb007fffd0f36fcae5347aabe95285954d0c2b31b01248194e9c66d6a1eb4a7c4ff5315f4dae2c4879da7387d3d5accd47ea0e034e85828669e5614f73cd0ba4138b0152edfac0ed0e3774fbe010d5574f7ae0f0cf442470f8fc8c59241a98191c90fda1bd9be8f67f45485cd900d3583fa5a3c0e4ddf69dcde684e1734ba6385cf5a627297706f2e8c47e3c916e05002a42a217a467755e7b321881b92a090652c74aaaf5083d73423cb7e5eeddbb7aa9dfc95321f69d2740ef02767f69eb56c2038b554e21824341aa76b97f8e54f8f80ec8b41c72a4f7e42ce327ec13ab667fe1bb8bffea0bcb0f98e52c967ab92ccc548cca58ca9e7d07d02a259480da58b138ad2eec9f6bfed5fec4597383b0e69051c18a739beeb6c2c3f5fc3bb023e111f067e1af876aace21cc21c585ca2d4a4d9c3e2fd283f18fc6c55e772af5faf8cb9be635aa4708950160787ff6af65e301ecd770cb3cca0a02b3361f1644a980abada6d766945c73ef07ebcab603604b649a3b977ddb390d16a1f0a99374ef9d2d4deca5cacb3480cf7f5a66638d087800a20049ce87bb2dc0a283ca52b80a0d99e1ef122fca72a3acbf047f41d2b7082bf6ec7adfb0a7b4c6c393b7f2d35f50e6be1dc40c23108895b0f28625f4736888deca35f5803234a5e6226c57df1493f0421a3c402d2e557cfc173724dd1167494ef4a2a3c721b5938f102d24a877aa1d20d222165e801567e5d910cc27d2bf5be759e1e12703f4302aa41343baf46d41176460558f7b4773198f2a655b3da0546c3cb80dc5857c2824a2dcf95e239e4bb2f7206808b520d9bb6f9e72b7610589cf43460871d451bd9b5163a9377224012d82b804afdba180a49d1934116c9ccb31d00e8b8d1aba506b328f2e44d8d95c951d25e3fdb095b51c23ec747ab48af84d378ef8d2478341b623235f7ec37d0e23af2a36b610a514eb2c5f090adcaf7fe967484d7177039a3ecdc521f9f7058c49650fbd631ab94b335975c992286288ced6b3c309a837b01e37de30278d2d60b705f3aa7007df1b2601c4d0c5243cef368f4c8809d240a4f6d8794b08825c3004478e1dbcaeb4485dcc064aefceb829e06fce80203a1b4ad8ec54e07d624680c06638495726b1dab7b64eca4eca13903c5df5c5aa193ed49f5712189b29798f09e61f1ce4f0154a21c7e449d898dcbb8b1bc1794e05634befe2347d084faf14f1e4f35bce4c822e570f3b711c74792409828275cc763e2daea5e7b693d54e6485dc3f24dada84754cf8978f4e1baa68eb09bd0628afb53f6744cfdc38a767d08e9a16749b0c755c60b31d8c9b6b918b682786591589cb79177888c55aa03732d1ae89e1096ac2d2e655e4e28763cc28ffb60b015f9ff4e7b28a4a17f9775082fb9e15a2bb9d11681d6a748bee8dee1065806534f74b2422e8c50808db53dcbd2c44285f4024f0e5b6a71d31f312c2c2b294d7e63e309bb600901887cb34c368ec05b385fbf193986c7f4aa4a329a6ca497cb424e046056c50dbfdcd2ec3deeef5b11a5e00bfaf0052ca20ed60593e01dbcc1ad0a5989728706f9877c58fd0e70d67a993b521b6ea1948c921199dbac0b203f967affdb633eba1293c90d85d444b8b9b7caa832a888647db05f2c160faac04d42443d1288772cc40911eb660a23cc82eea62ab5e41174e0f7eb8176fe366dc042814d7712769fac0459891209863da87b8033b9a3281da55933b9a2bbee21a69ec3fd230f6530f72141b71f64abd57174aca1dca7ded252e22b29e3cf267eaacc018b5415d1b28fe07c7a1e311fb59ebca2b358e43ef73d5f88e340e2c38d03e16f06d574cb6e6bd274a5e25fdecbc344e02d4eb2cdf5f89e20150612bf1c34baba9deedacb921b818475ec1966a9120abfcdf02699aa387c0afef224f54a9df1873b51761debbf4ff3bdb55eb604a2c5b7bf04e00d48a335cfc887b8eed3dbab298a928b2b0196354131901ec81677c9e69bcad36739ddaf53f3e586421ce31684bdf69588c577aeb5b193ad19f2fbfe96b4df9577e128b9ca292dddcf600dfe1e3e111f011ec59820417fe191ed0c9e85e0ba568420ff287b2a584044f0ccf686957bf16e2bb55f43fcf798ba575456b386440a0c3305ad032d47f83e16511a9a9018c5b2c8ec370754a00574d381b55528916c43a5e6906e0e0cc81f27ba5897eb0de5ab7c72ab220125785307b66e60f070344f742be5037ac8e93aa45a2e7f66a05d62002491d8c747588f0143b09380174be55e36d526bf6766ab88a710b87e7b56a5e1ef00ee9f1cbffb8b88728b9310e3104866c9e56be91d53a2f186bb856a0e296c2028ddf48baea8ebb3f1d2461f42f42f9ef27fcad817b539a60f2f8be66cde38ebab895947879e8b71bf1c368475489f449b742d5acf8d68bdf6618e97173ff94681e8a62291b94e1f674bfb007670b59c1b1d151477acafe686ab5ccf6b796833f9735ab2c3f47490e6a8cfff96e046a9f9795553055a17cc4e1b4dd459ae9cdd2b226ebb94580591210e6df33bf147fd29b8cc657ca0c1502a134aa2e4763aa42f24e1a6ef09b175d414a81bcdaa9d95bf9a0bfe2d0ee07ac2737a887a79ac01d309e429a49b9e6d7115e9da8f1fa286992e8d747be5c1a0478df1b87bb64d40039a879c28c29b8d9ad8a37728a5c59751caf217bfa7394a23fc7498cf2a30521f342bcfd4dc1a25790ac4abf2f1a174c55345a1d0874282de03ea22d75eeb5e3019f129779b4460b8dd57dbf6d3e74c230fd6bd46f8f91a1622a68b4a88aa45950610b822394cfe2f1d4ebcbb54ad276c6a7487ae4c492ef75df2d44bb1d8791575cfb2dfdbe41e648e7e0d3c88508cac8cebd10b015ddaa66fa698bb9e9db91d6b7998facb9164f08683879cb8ab75b5f9df6d8ded11f959c14a98abb1eac55350f754837e217ae5b1e43760a199ab00fbb0c4f5046c9e558dc35045f27b11c174b4a5f843fc0e733c5547d21456de8e900546a6698abea8a77b51172b314d4d9f525029eaa029838fb0f07ac3ad0d45550fe1a92707f5d8793ee4f86ddad7b042a605909ab55c5edaa767b254eb48a94344205d24c7b2ec075564df69c600677d95f02e1faad86a139faed74e4a1c5c10d5f4c1c6e5ea9b7d7a9577cd36b847be0d037fd129562dcf0be637a1f010aa86b839a75bfd2ccad63660186be6bf255b00083729bcb3f6dc11b51daf648ce88db1d46162cee0cb77e49ed2512434fce26635a25543972094dd49c8fe15a41f96dc8263a078dd753e3eda44c4114539f5943510f6d8c22e4bbeaf6f1b8ed7412910a6e8fc8f2dbf33bd30ebe2180741bd424d36d8416ca9c51245607c933a0c58737ce770b31d4bf7852ac5cbb00da2c0e38d8df39a7a671460f73911781ed745c410be295881a3c15fe7cf0ec9ccc05f6da8da8777590ce1835ca844d102e9b9ce2f5b53f9f150fa08cc8beead6033309fab07433b79a9f06ff37f940649be7bb727743b9caa5cbb35bbb5ba85b14aac5bbd7d2c91c3d1d4c14083ecb907b7f62f5b2ee199bcb2502cb5ba0a96aa39ff05803e24cf1a4369a7189def06d3943463fc1e5047bc10134f7233b5c96766b1f227501dfaef471c420ad3a9892e5042f1acfd1605a8fed605544d0ea286b81530205fd3d0d924ce4143ab642328cca09924b35b7f9a8ae0adc056304500572f4be75a31888c126671c0d338bc73d086043bf9635cec08a2d792467ef431a52d76e75540381846e81f5c095e2c6784917267179940d3e56398b48a57d45009210296e222c94699fbc00092facfac34e6ff319f8ab5649953fdedf9b3a67e67eb9e9236fedf8c3d23805d1ed0daa7a2d083d7ce5404a5fca0822e0b28340f9d0883cb7ef00bef06aa13c0b7b7d1c68c6360d2f5a74f0945f5565399e4da1d2651f2d31b9babcf6cb7127b4e6e84e36ec7c50a4beaf33e8dbcdc27fc8a1682f79103ff7cb6d920ff6ae8ae490e488e511e9e177cca1ce95e9de7cd236a4a7c71dba0c2924fc14fac047e350a77297534766a033e9c7aafff22b572296b8fe2d84fbac1978fc9f0b36fbc8b6d94a4a9c1b589d4e414c8ac66ee6979bb8e31a72e2e71010b8489b9b8d2085c820c9be99621b455de523f5a5a8f2e90e9076fb13c98a9b94730d6d727e32f1a21df38e03ebf8172455759593ebce27442a6de68d646696780cb890bc4a63cb88208a86df7a92edb9a9572ee28c09db186c4272467f08fa1a8ed96728626d3e5c158d0dc471cb9649e53e3a31a7243b0bd00575337d1a0a1d6db08563b995a7bc36d93b7a80820178ee14add0d95f0340a9b6019b43c1d4ec455a0a8e57cd7b3f426227e7da5c3b02b4bbd87ecccbf2db04e8abf7fbbf1aaeadc503a919032812ac848c9a23cebf710b3e843ac222f9db48efb976676a7062ded8cec446a45d2ffbab166bb6b563402854102601bfa169c542000978809657f0ae8b7d04c2227e6b747dedead311523b5ea87be50b4e6dd30dc177dfe8ca536e9a5f8557c8946aea3d05ea1f7b93f851403788265e74b565f41901cb76fbde42df21f3bfbcdb32186a6afea779185ecdd6713b81c282aea57d5516b1482a4fcc9206ecedaca5646fb94eff5794f192bced0b29b1a2090aebef2867a1134d79abdde36c96c01f307e3e448943cfa19432d505fd29ad70d1d4667c3dd794a1732c64913328e14ab029528c12a12c6d943eb7aeb9e6edea66172ccc2f4a48a85d1a8c28f7ec6286c64a17cbea4c20529e93101b85fec4f0d561103b7d690eedf809e749af83e27085b8e04f68f8ecd3aad8b973784237d6e07841e5f3d6d07baa6d67cf4b7d2eb46b36ba45700dc88de2105d1a5ade74eec56292e44eb2e7c1a9995df1b0e22e77f04655ca67d393ef36578c9a900c4631cc8c898be11b503b25fad7b48a2596c18bf7879c2d4cb877f3584208ee338945847c674c5188b71927aba9cb87f954a455ee981dad6d7c35fe4b37adfb6c8ee80e6958ab3dfeca5a3e495c9e118bbfcb552245ccc2ff17e5c321899c4b5375f4ae36205cca273f26c7dbfc8326cff65da6db4ae67c7f1b9f8e2781ab80db6937be914476410aeff411976d62ec3330c6d234d20fddda508eb5d59e75cb6bc26c26617aeb0d1e14c6c3fe5efcd4e26c7398f68dded3bd042c98792a163df8a12e8655a59d1e16e801c8adef9ff15d57ed94279fbdb1a3ec9655582a5ac152bf8fad2b1ab1c8f2373ba678050757ab1fd9aa986746ff1660bbfb8f30fa4f011f76b0b29cc45d886dc5dead503bd8413b6e78a0c0fba97489bf6a716501b10f3d10d94039679c95533cc162436efff052836947ae3f9963db41078f0408ee626afaa8a3cc47964525906c8c613cee4b6f3c84f310153aff202a5e3834977769f140f260d2574eb3acc6d972effd55493fc7043ef4bead7500de22f066e7c252c959cb64fc49fd1442f0c8bec04ac0569bfbcda0190661f0bdfea9b9e55595acb3bb3fdd67ce735befad62dcbdcbe7850deb09db547182c4a734fca8eda228df43788b98844eab0d318dc994dda9390a45ab3060cd8f3ab58496ba470bc973b6f230f28ef0279c16edad13386c1ea40ad1f0e91d1b01641fd538f3b88f1b31ca31152f0b8192e710476286499bd8f2bde657c7ba9e7bf7d9762709c4918b23fc242763cd2d058623ab297372e4f99260d28b78357b2c003b3f2cc73b1c6a723bbb65578253733587b60f6e8c6d613411f7b14bdb1b8d8d19136c27318fb14707267a3972979d1ffd7becd8afb63aabccfc8746ae44d68603ea217c2d40c8735fb3fd35df3e236cad6ac61516ebe02c12f4874c7da49a9a84301d3ae4cf3f459e7791be4ba910905dcb5de12673bda2e998693d7e93412ddf62a5d38a86cf55e06781473acf427292eeef00c1834a743ee8f0700a0e70d3abe680a395d2b1d8915cb0921551530935171d5268ef2bc1b6fa7ce0464e5381eceea96ce0f09495f644a806f1d9c67f3dc3de5a0b9b5d45a304a685de5207c6972e93b2a2c259ab945adbe63e14138be16957e0c34fb100ed6e2faf6d80f6da56800ba0ecac5680302ff3563ac496fa3569bff5af94102458747a98077e04e2d201304a71d1cbdc6a704fdd26f0cf32f8a04cadcff90281a7fd348a9c0be706f2817abe3ed3740a95fe29242b3ea29ce0dbc6362b70af3dac0a288d53eaa06e288ba098df835c4326cc76415780ab6897345eafebdd0ce4d01c625fe46c3b100705c62a07427822b155d26105276575b1f60e56336574c1bf788d5277415ea6af2eeb686845a22e565320385b7d06764967d1115e6a299b1d0edd43334a794195c8940d01c8345b00f325ba4c3523030933f0cdb61ff441850ee43ba4cdc0f2c16360041975667e54665085f92bd536235b0184922f708e996e12f04aaea80aad19633669b76ccf8a5fa93b76cd7f100d6d272f9806e14f6214b88048b36f4e4a0e62a953ac0e81590004ccd1b5c3950e3d9ce0207645c7f27c0b3d7f15cff4b78a133bf6bdaf02e988863e215f8b3bb20c8972ba60fb10073d1c2f1734a79db8b97384bd2b2b0c46d4ddf482c53072d2591f0c4ea3cb523c55e669812711218fc5d527083f63ad2ed4b65fc80eb3897c2c4a8a2d90a205f059d36d15f32d936766a9f7681c9daf731d0aa800bcf3ff15fedfd3be9e633a4bba6481fe10f0d378b63f322d7aaa6b45e978f8c46847af3e73aa8eb653a074e056d23e8511edf1c60a67be3eceeb195c926172aba2bf4f47c055fdf06bd18cbc7781cd23f58d8e946f1bc00e754a9cbb85a44465fd06062b01d6dfd9fb24b27d16946b0c120093a8b4c3c7b93c066e8955b8452e54d97107d751972e42c8d282ccd83cac0c7bb8a0dfe60a90b858d61b34265e301c9cda6063ebf574c16fc313a499aa47b178ea4a803af4693bf099b63ef21365355636d81b9d3eb4b98855c305240bf9937272a8445212f42e15532b2452c5eebe845b511be310b20ce2f606f196354f3d9b0174661c01c5d58f435c098573e5cdc83f6e671432a1697964c2ebf4ddb15a05ff1d65f634af1d603795eebac74cb1c2c5db4e4cf7814265a8192b766094b72c9770c7916a94e76dcddb341cc004fee28ed6c9545cfd138e5a92f082ddda39a7d99ded41a6e96096943d76282dd7c91e8b2f2de56832256a5dd60a46a80f13e4c9a8b8f1a5c3efa6579293d7a4f08d8b4ac9a6247db304fc9f5406e227f6764cdecae70a7a6d0517bcee008b36bfaa2b0ed2db9bef3de584897715c232bd9481a0190df068ee4abcac7173f5610b00cbc3dc8013067f3a57650445a1db59b2cb8a15c54fc88b990f6edc03424cc8809f7ccfb78c70e7069241e2c32f4c1dea5c81264a83148c0392b50cf7608def79785ee0241dea6b1832d6ff661b69ddecc0bdffc4ac934b132ec5e492dd890ac10dabcd04080c897dce360c676b85707b138ffa331c20ad14e83a2e0bea2194a5b24daec9bb4b1a6d31ac11cb858ff7909249371a5e1b03f88b6d66ada263b9dde85049a3fe8693be5431170916c65cae7a7b03a1f9f25a87383e1f647591ad11cbc6925962e1bbe5293145d138bc9bad9d1d26d3f79b75737ddb2ecdb9e37b2a66904b1dcc0e011f0ba11e727404974860823ea4dabac22bd13254c8965865bf4750b06bc62472274dc4a410a9239eb03cd8035a4b9a93757b9f85d0a0b33d49c15c4fca9b35c17783cd64d5dacad1e86d76cfee3022538ae317c94502210712d9bf0e0a46ae1d5c1d41b5a1027914d2c7a4d87e4d6d619cbe064b3a942946166e15a0cf7ea696afb35c16203ac06868460e7c3ee38b93aaaaa2c3ff9a95a21f9be585e9c5fa8defe985330971f1dd4b930092743fd851533a9c7561b77e81e3341aba0b92f4e479811239c70a2f6fe74da9df4884ed2fbd7452a4cc7adcbab4413066fa7fc6381fa760cbd2f679749081b500693083fb5c7140fd556191445c81ee917f96e6c2492cae44fb8056f638b02915e510a09f7d74dc960e1a808e7065eff6aa4560dd5e457235cea8575bf1875f8d69e5f7594dd3fa1045b2b10b47260dde456a5a449a345f7d191653a52b5fc23685e644735026727c2bc1d16ec6a4b8e8430598453625fa754a928242d640e281d8e716795e4f1afe92f29754c121fa1dc26a74891775bc7a6ae8c24f984a5912ef3756eaab59c7eee0521e0db3e097b1f3b17c2109a8a197940d4912947d1ce2d12cbe5e2e18a6a50689835540924e5e65143a666d3bf3c495947298c9d835e4d184687c7a577a12ce6d42f4faed98ab831a559cd92ab2c2a79c717aafd4f578930bbe0efe48abe132d62fbdf5fd63c12f06349a8951943ba80f7e5d533a54f4493852222149119e32a6e9618be221948265a0206ec9e319646c6f117fa5316dc048b6b8e35ab538cf00efa6507254a382d8b23f4d8cb942ec597dac1363d7f018a4be857f83adb748bcfed1ffe30260e7008d2137c116fe6291c345a1add7504b87ec37c060afee8cfc8dd697910d72c5c63518e84c345b6494a8fb832f74d3e78b6f9c8e8f173048f3da4cbae29b264d960b6d229ea29d9a785a8eb847c6e648bde53fad82a74bac7b375b5e29b62ee713c87ba9a0d39f4af812b1bdd71ccec45a00e9d3805b2cd742e1d72a8084da90278f70672e2e883085a82a9e2ded24e173408ca1124f98f4cd5a5f29af478560e18a3d41be1485cbb1abc39c757585a46d44be81fc50e5ae208f0a69992ea012190e61e8e0dadd290e7f60211fa45da50b105a0f2c3210aadf091dd1bd40569f732630ae7efa31855d305f6c21f4693ba0c69e7d9922fdfd993fd1fd9a906a0b205b4742e9ff14fe927669dba9318110443f24f4479990928c90ddad12a66f9a423f096417d1fee08ed1a34a3caad5b2abf1a03cce34985edc1398f5ee740ebe7d56bdc56f628c52ec7c64b1547be574c4e72d98781bfb93194d0753d7573c1cf78c0e2343fbd6b5d0e36c379663c87e4d3d55b7e20e2c1c30667aa9f49e35c62152f5efb204773787db640b4ac0a9491c8bdc5b8f890d1461ea1d61e8c97e00701e04bb5a41df5e7f5f4be5140bd48a64461742bc168f532e0f77c9e595cee1d288302d2f309a37da9c7ee96f32f5f7f6766497ed3090cdb45502344c3d2c6e5107186afcdca55bed4b8c6913680ba1408a20d26ca9806eb3f2411c1632b81feaae6515da217a2a25daa9dc83bf9b98633e856e03cea250fa14a5a4617fd4d0156cbe96777896be9967f4cea99f64275cd38b61fac96218270b4e302e24b9569c961640ab9e38517e2abb854bd9fdff5e73b12646550b78d55f69ed30942de07e367316f0e145b4e266e9cc277be234976241afd1b46cead97de0f0a95c0fb33eb78077947c62875ab8d498e6da13fd4b8e6dfb131e4b869fc47a99b677cbf722b555eaf63de5fe5c89b7c2fd59bfdcb50b90079caff4252fc2fc3f558f6c6cf4017d8824efe52d5e4a73f8e95ad35ff88f9ab54e535a300a3680b04bc264dfcde41fefbbb20bd2868530184c9eeda92da1587eeb32c6da6e4c72d9e23479abfecd9ad879deb09643ab3abf6c992763b5ef8a97aa965455fb95b131e76b4b7793f5bb8e477ae58d0669539587c25019fd88b5685c4462042f67dad603202051e68d47749b4aa2701f0753e09c13179aac7a8cbfcbdc8a5c1697e75353427ca7d238bfa73953e3882335cbfb169792ba85d02a69608ddf0bee2907c28a6ad18777435f8743138dfed9e21489b54984a38f4dbfb952020dd99f9b43c5f182b926d96bbce908898da5aa727c0773ee97054f702866c4177d049483373bd2cb312daad3ab764058e387157ace2f6b586f5070eccc5b3b6376444845c63b57e7bf7d09ef247ea85b455b3bfb46652bc1b9e731f41aef24ba89b383311b9b094b4877899bd4d2ac98e29195598a0cf80c8c223bf9373024b7c5e5426cc701a907d4f171c95532c87a9c2e581be14741b1eb979063cc8ebd234d5a53b50dbd42f5429972a553be0dd6d21db50fc56537e3f50db48f91c22d79c65466283e886887a8c17b67734437edfb5469ae1017f66250d5fb1862317c0df1dbd7c571a9cdedd9b7d8865719319f7cb9211715a14af3fb336d94e93b90ec6fb465919cb9d45226877e390b96a646634ea79f8267dbe5582baf1ccd210d2d9586e13d963903c7a2962d7055be72e5f179bea45c49f16c5a747df45d6f6bc94d88cd899e56bb93dcbf4b233cf0b2fb6b8a9e437bea1de7fb7db1ba22f2d2050a71618519c0000210d770f17f28d83d44736950106d76f2776710f5a77fbac537fcf15a01f4ead81e94afbd2b1dc69ea4aa8f2538caa307e7d09ce569aa956dc80e4b5dceedff286d43fce1360b53c019dfc301d5a8d85becda843525d86541d1bda68bdd519c30f64ee1ce580034a691eb587884364a40e8939deb140c96c2ae2e7a32e463ee02a44b952cc55e1511fee54a478fb505520a02e1846da3d72e185513dc2b48210883af60a021e0ad38406bcd5c8eca1191ec221dccb4dfd3590143f234012873508dfb6c6630394f15c854ed1ff5fb5b6199eff1e79282662ae92e54ab7aa75c8b0c9e29587fa42c2332be2d458a519c6a4e8a9a9fd0beae58df48c88b816cc6dcc87b730efb279a04a81a0502eaab70b576b11e43123214846a48f5778003c60e17fbc5d5c720edd05f138f0c5962de92572b41ce2a6deea5f9d5cf86a1f3a1633ae62ba4076bbd2a382f2be4f17c353d12d0dcbc06db890d4682a8a8c4f278f7eb6fb22771a9f64bc4e476ed4330ee9e8d44f38f687807c3acdf9970bc5592b808495835024e05281a3b1d98851cc236cb1c020b725b09bd3b871034133296a1f9f1c42218eae92aece0e9d345f66d45638d708837afd22a19dd76cd9843243cf399cd247cf2c9eba71fe6def3f57e3405ecc9cbc13f859fae0d947c70ecd4c145ceb2ecfaa8e74f19242e62289a3f3df2e0c076a92e8b80eac796c81870eb4defdb04a411819c8aafbd29deff3578e343181c88a47d298f50c16193dd0319e710eeec46eec55f4f0e0aa46f301c1d346cfb7e1406264174511821da3f3214442191ad831b7eb667bf57366598196d0721d5fc74ffd07574ff4309e6c60726d79f5fb55787490273f7c96cb16be8784595e0ed4c3641aab45ca5d084dafbb269c0fde860454378fa791617f9653908eae75049accd7b8849ab9e999d03aedbcddb751da751aa4d816d7ac97306066f5884e01d20ba60b4d0d415acc6e0877818bfa442a4613d8e1b686725b0ce2a2d43b32bf368b275101bf70682c989f010c2bcba8ce8881c26f4ccd3f78eccf51517725e8bc497c8dae35444e0458cb856863db200dac6be6b3e4abad011afa64e0d83c637e5c9b7b1fba12ac8001c522b77517f08a41ba8f74ecd4d3c1f56a161f44e170c9af9e6a1fc03f7e84bd91ccd014e84db431fe552bfebe6d1948dd640f09606158c67ed409eda733bb038819f46186f27e8c4ed8bf26fe131ffb20f6f301fe3854f510324733090debc50ebe37f1b231493123f38d7279ef47e05127c3dc40bbc6db278331d6ff08b534dff95dd4cd1d453edf40a86ad65ff83ea9348555a667397f83cf3c6d1710faa56317b1f4346d993f2ab047359065648054f8905b36134988c36090b8315f6f04615a3fa403d899ea89fbc977c8bbcde492105ac0b2a58a82ce62e54b5c42051e662d87de2ae4df5fed42256042c4f0c00bc21700bd34224c4ce6cb90886d0167fd2ab29519020d1104aedef8f45ed25905cfcaa08d8016bd5a586c0a9305dddf0776f7c02685894b76737ac48cb09ce6ce7c5e247a692697a435c70b9146c2b8b86e953602777a7f875453e9d10014d567d0f8523961cfdd2259205124cdaa43aa59a32938d244d92e3884bd995e1340b3c16c0e41ebaded64c8e73b7d23b2f34f0f1e51ba0b8e11f88a7bac86237d7dd9f33fcbfa9ac28d0fc699a5fe1dcffd94aaef1adf6c74bc6b43628ef23db242461aca580e895ba0a378bb76ad4919f4e76221e427700892d39df0f0354836649be2cb85efe9a72951b74c2a45994d22a6fa6651bf4258cea007ac2b6da62727172295a6e729e11e96603c9c4a41622f4090621af155a71ca75b85519e1badec424909b506b249344f389e26607d70eb970fe928d00995861686aa65319dd0c6a6001c37e83f19d13491e211545f1a0169f025556cdda187aa71fea11cc6ed6f1068660fe8c3c07591fd3c79ac53b8bbb664d3e06bf818f271b088d61816e72b3b154122bd44e65e17c670b6927684ba9ed24581771c88fa5533732b06d2d8acc0d809c542cafce89e1d6d626aeb8fe046d43b31f23068fb68102935cc03fc728aebf9cd0d4aedc683078e2edd0538d8e435e82bf2312c5675229fa3777b077c80ac88d3146ebc7db9ff8930ddceea44dee8269e5de08e7e98d866b3b5f7db727206d95d4949dfc86b77801e67a78fdb84403e0a683595b6b54c06467b83dddc8b0d368433d14d5f0564c2959edce27f40ae6324ee09159eb587a320172fb3395051fabc25b5c085af6a9b1fc040880b4a16e41a2e8aa1b91d70271f6fbe7e16be58e34a467d38db07abd07e7a4236d549efb9ab395078aa7665af832a06c70a629ac2df194a0b8e9eb4dfeb7d81e5923559a80e96bf7445d46c345e4c939a4af575e1013e08efe8fb35d78cbf32acf145869ae616b013008455545b2b5c5cd874b4a8e54f8be122d68e8a8877294ff01fc8632913a72b2d05b4e7d6197a5159c56dbcf8c52ccc36f327e50a42bceb52320c07853017dddd32977beb04eb60c0cc91b9371aa466b92d8f0c5b428173ea4521c4b8092436da5a3eb63b4d74b08ac9dfdfbc551d818b078c4c84e3bf94eda3f11c14fa6df16f4c6e27de964064cb7a5dcd67ea6a55a51366ca807e64984ee9dde650565c6e37017ea9dc1e4885d99aaef3b3f648eb1b3d07b3de397a033b5cdf16ee04f9bbab7710d625ec34777b28a2275deed07c7d16a9c72f79784c1fc703593db6167aebc4ba09685a40c2af4dc91556db956460af3a5b9ca0e67a40da5d299f379485cc65c45bf2db2a23fe70a033e74226b2695b51fc66236f5fd00d7b87b7a6b35b19e906c87baf3bf794dc8c2de6f6c44d8f289d60ed731a0b7ec252d4b6405dbe65b0f0c647ef8d523a595949db03991cc048f8b329626ae34a3bcdd0538edefd33a9e9133a82054b6efdcbc41efbbed81f2787520529163ded86cbba455c738aec4b097f6483d01fc7797b23d89ff83848d6df532c543ea92e55ee6decdaf153d456932aeddb84a0787698f09378490c2e53390c054371f9f07b8a30d086e65c9223a97a8b3a9311e1e8ec6ab9422cbf1ad10139901cb8421776c61dfc4de42dd94001f7d2b8fa5f148f9c4a5fe8367c7e3db53dadca8a59f39ad51bea3d531f1c1180deef370fa42b8c6cdb9fb18c8b7e8c502a3dd173d0a4cb7a574ecc4baff1b1ac0e8a710d316fb906cd5fdcac9c07be5953ee95ace0fb1062fb7f0f6e22259db957e1b868fa6af994a5b7d92f983ceed4aded0d6d491ad3a3a14a7215578bee72b72977cea65a40113e08160b70e3c28afa1ac8bda636b0474e2d30f049ccfad056489f559e9572a71642725ee609211655572bdc4a0403736be92cd7a8b8e4478ae00787250c76fcb9651b1f95dfe1cb0fcb7e674f0142701afb695c9907ef144ae4e8ef1dfa7ef034f194e5c7ec584e5c139e5fb13b36a1018f0d43824a6dd389d5b64eeb6f7fa2fff9cdd5181605d1f62b53e533888d95f9a7a306e8340dc94ed5962b8e6ad6b8d12cd20062034e738292d889c4b053038c5d771b7e7a2bae05a171b447875bee53a72d1c77c4e985356b96749772605cadb6e35101c29c5484a68398f9e7565c60a04b093435858848c621cc958a9424856e9bc7c8704ebee6fca6da2dbf82609a20b80941a674b934df1e67d074a9a202c82f6a7ac59b020425dc13c8fb06818303909bed031063219d9473073334ca883991d97738ac80271df2d08cc83f0cbd22b3b06730b62b9c6b8b96fa1d2e76bb072da39e130af20bbdb355e27f385c30d9360388d2c07e96b4ae8932323b7ede5cd86309d32269c8d4aee88caf3392db58de583002fc486a3c47beb174036fb8353ea06cdb0c210b766010b8aae7e741f4ac6143e769e4a71c40b98f492d9a1cb4a266131d28a7d2a9f96c21b4044e693c2d44d88c6e6653dd420ac775af0a705815eefd76d0d4d7fe59043dde8364aef69dc9960f4640f8bd1a2e7522260d175b84755ef3600f2d9101dae68adb092c85f76e38924d38df0f64dfa24a08be7c1e40ae3e1945f85067627ea158479d6e143936e0565174b41d5b040055d19d31a91a30277d7f80077518e7f283837260ad71ba5e5dc48b67d8ae43df1a4d14dc5444ececb098e6adcd69d1cdac93e7738d3fed0c23d80843c12735925cf6e04bd2eeb3879153eedd144419b5adc0d588d9d608243ae0ef8a61fb2d8a5f72abef023e9542e254eda7f502175174d8c149cacd4df158210b28522dc13ef687446f85cdd76293c3cbff46af2c041b408cb4fe4e6c55f939a862d21a53b1a8a4020162b08865a14c0891b687b0054569f7090764d4aed600d1dc9116c6ffe1655786a131f6e436273b22c2ff202d788b9f41d0741093518b64b1ac29ba09d1ef46333e0a8c53b06d01efd97331f8f468b42c8fff48f784955b3b26d58da77c566d500d934a8b24f892be193f55687499e1fd5cbd3059d8244dbb879096b7de7caf7ce589c40f79bb543bc4d9e49c962b9f65192529caeded3e670373d357a2aefc6da077bfe1bf345a8439bce002f7a5179215e68425d1fb7e3492b66812401192272ebf83671f3276b209254f9ba07406dd289493fae2f04929222fe1fea00246266ac7817c8fbd658a8a7bb2e2d5343e63a09fa7a3bf1063aa6b8396b9fd18a48edcb4f608468ceb99f005287c737f1b186ed76ef9e5ac82744a6f6a62534fb825503778771b423b3baf30aca2d652fe6c67772fa10e321362169a6265ca95730f6c6dac0d665440d2a793cbb7c18e6686f4785842fbed50f7cd8fae2d2af1184777029b2df7e82e46cfcef97197acd7092e3b1c76dbb538b477ee9c629fea7112a99c8f1688659af8c377d24d45d755a92bbd20513d7f200e8a60a04b5d4ef76dcd58b88c12fa21b436bd21d8aef79e7158d8a0e28fd0907c82d8dd9d6be7eb57491fcc56782bf49bcaeafc8a20958f95d7eb09475f56427b95d20438dda317c7da81ebdc37cff693b2e0119aa65741bec942cb16bd75ac81240db28dcd99ba681daf211770c49119b3a4c18246dccf0e957a90cc5fc03efbbefbb29aff82060f49840a29dff7839390960df5100b9309bd658b1003a2f37e82d29f59addfa25e9ef251d4c53a24edf84ffc848a1f7b1b3f742ff3ca1c7bc1e6c1e6b342eafc6fd5c495d79ac86e0c39ec6dc9059219b0434b6d7a475e4ffc04486d59f1d7fe931e3580c0ffd9f15b20b0689ef301b5cfe268dc28861660632941ee097657d4a272520ff2efead044f90e73a57dfc7b30a876d1814ad82e505798afdc27a7d32ede62a8401a3139299de3bb883813cbdeb0fabce080b66ac6695a24adca2fdfb37cd8ff5516b8bdc8a1b0ca6d262a3aa41f2565312c08d9052d262b44f84257e15b220ec625ad7d114a06d4af907207cf9126fb93687528566c80fb3b4b0b0154668d4bb1218a4fda0d9aec36398596191a6fd730887697d786eb4a761a51a98263b4b5a14d4b8f82f19e24270be8b5e8d8426d76456a5cfa97f40d61389e51183d2458843b110b01cabb4b984568ea2c6972bd778ba34fda43b49ae97388dd0f0c6e6f77b3acdfcf5a6d6e9ef5ceeea206467c2175b7d2e9cda4e51772296ed87ff35f3e4a6f38c4ea9866c3684df4db3af6037f3c1b2ca17f1bfc472a3fe165bf44f3ba03e41bdcb97d66a4a306211138ab2ce4e16268e628d2630a28f46447d50cdf26f3bae9a3d6a4f120ce4bba577d5e44fcddbc331801857ba5e2401128e13e9373a86216b401d2d29c1211c8bd988e092049a7748c7d0d9d9ee478189e4181d44e9aa6fcd2720889ab287c96a7edb6f880de8eab113ad415484edc182fe270ab29cc7ebd3467d415c13e7b4b09ca853790057384933ce5c35b0b39f3a84a59fdc4e766e72c141cfd2378d44cac0c596828cdfef45c3fcc6acd48b9600fc78b8f03a13494ddf4bafb05257f288fe6e2cf0800a3f80edb170ac38bba8b5ea09d3f9dfd47b7e9d9cfe77c2e82019d9eee5cc0bdbca46ff9b844342f76cdcb65803e1cd7bf426755460d3a4d8649ac307dcd0039f9599bd9e4f17a5435630e43c41189e3b9dad641d8a17da500a238d71c2abf67f5bbe810415678ff4c1b92f5ba4724a1c8871794fda5cb2eaada02861d502e351de049a2a699a2f5c578f2a1bf6598bd2d42b11a0e432aa6e7a7f9661cbc5b96b7457e7595c4f0ff3aa6670cf386bd41f29bcdbcc55b58b54fc865f5f9546f77cdf112f06a7d320bada20a4e1054331fd3a0e8a65113490fc21daf5158e512d7bac49dad0bddb95ca9eee43077f644e7822124d26f720c0b8f594689d2c6fbf1d02b5877163398e66cb0204370ab215570be6aca11def42faed575591f9d6840076fa36a4c3aa5f00bdd45ec5a992fff0aa69285429db920f4378a08f70c53ab9266f3860172093fc0760091df6f42dca973492fdf73c9140a32f1d7e2636fe6a88b1798d3148a559050402662f66b116436ada42aa20d8e9fac1162dce121133c9d2ca3b711cc105182146daffa0ac71310ccb134d9bfda99f814bfe1cc3feeeb16b4cd2d442cd0d07b6f0bddc3214a352030b572aa80ea257c92998d575d9fc091cf51fd8b9f31e48575c25f1bb7817662ab786aa4bcda95d7d2bd226a4731b1d26bd03d075df77e0b6169344ba1b8ca10f9c142c75b2adfdab5b19af74e417dbaa7b2ef1bea15adf7bd87d26c965ee1758c30c52a5324cc12b50e86c3bfecff49af0d2875151223802a5c9f98b25834c7f2f971129a551780744387f568bfd2d1ccb09b9e54e7fb56836233f8d9841e95a3b79bff83c377f3c68fb2ef9f657982e252d80accfb9ae57b1c1b8ea28f2091eb5f9e29720efb05ebdda3252c18e6edb59a8d78a5ed58ed6b0fb1ff0b20f69881c79acd4782bef2db0b88597faebaff95f003dd01912068f6e28af2d88211accf0c86c76da48384a44f93e0ff78ed66f385f1a43a27a8a3c5dcbcab68cef8c48e6c5e52ec947aaf6423785f06afdfb85c8cc60371fa5062266e4edb0aacf8fd89f019e33e2b9f8cbc1133d7e0427c9d53d27d594434059226e3c872716ee0da2e8beced80a715486fc175d7da08fc83458c433920dac179f50800eb0593f81230b443d3e471d4ec8f8141cc53ca8534961abc5942e953e6f3088c6758498d5637884495b838281b890ce3b99d3d550e5797467860256ca946e16c1ae6140e1669edbcd98948f4bcf1db30846c56113db56d6e23003ac34b16213f3735b1b84b4aa9b1c87a6d0e4582ae0f0f2edb2ae6f0f818a06353aeb704e25066238ae8c4b38a6760e9359efceedc040aa25ab18086db0c20ef3a5849cb4d060be24af984b3228fc931ab7e5bed216fd7c121bfa4aef5a54d0fe6e37867222025d6fba68cf0e87227c2225b01b6ba633e735dc07b1144f45cd524a0d58bf5fc47670baf7da553c2227d6008d6ae798b9a20e1e8c90a4101f6de4264e587e7f1cb9dfc572893b706b733b35b871b8d5df0d613d71c0dd009f51fda3b7e54bfe8cb335569af60be1b7fcb571244cc0bb41b012d45fd50ba326ef48f98d16fa8e2073763401601e05f6022797e109b7bf18e533fa2b8c79dd5afa059a127f27a0617f851cfdcee0b8400333e58c2d369470aa77c7a8f90cb1c370bed15c1917b337cc8abb2018b6bb7e42ed54a69ca66d89213a8c2ee2466a31e97ba320c9b7537336bd1283e338c39f92098d7761e0c430386b74b02141a4045e0c859bf2a3570f1c45e116bbc7926364eb8086b696e04c6dba43f4e844b65a8bac8a9dfb582a8c957690abb171ecc482dc1eca1360fcac748588e037cfc998bfe84b9967f43d4f7e2425c478e68a1f4f65c6d91967cb5cdf01e9131f41ca1b4a590db7087cb298be7ea721e6672138c5c8c0f39d86a1f571b7a0d017ff6d4f67ac8763d7c64a669cc751afc241c0fd01524517ed51c2cb766048a0241d69db116b03a2c110b3938d2afddf205bffbab1256f0e4689ca3030a56b52c80464dae01115548c11e75221d0c72af4084a1d5d76b236576c3913f75ea724e48e576f29b1b5689045f7653ae87f2735aea4f659fde5a0434d9387e2283f95018478a61cfeffff6fed6dc548652cb3734053123495ad003f2a5a838e134be245fc43d87f2fc751bfb3aa481b926927b7b1b29893db73fb110999ace26711676a176df979ad6021cd8d1e3bcac0dad52d97a551c43aea95230ffa79390542b1f20034df78d52cb39fa2fef7aec36ee67559e9df850be035668734b863c9534ed4c9ace38839198cff04741ba9a416a3a581ad400e740e483458213ef4371fecce5de979b343cb96c548b369913b3c6d81b09d24b4d0118d5f02a368e758ef50fe3c6def77586efb258b9091bdb3ba93b4a2aa7906e25728c46c81a989a7249e3326c20d797b9e431bb9742b3dd20aa05b5263ac76322f945138d59819999f52c496a0294d65607c013c1ee343ee65612685aa31f32624a0316e0c4ea96edae3f4c8e56bbcff9d7f95222230f85ed7cc9b65e207730e9efd2f8742eadd839be7eb05be718327d3cc2b9e5780e3b708144232010d6f084015e1766c7459fc34dfebe44dbe00c9962730fd9d9b192e90f3ab50d6e749e75eb72441cbf53f818ff0a7b9efcadaa933ddf3ae9082a0a831c4c1e86f0da0b66340d063d5d0cad8efd27195fcb7e5999c3c7698042d86c5e024ba27d99047d1ca5b6aaf0aeae49c7cbf540794cf96e8c54687344c633e1347e6ccdfba091ed48d1d39ac69447f5da9cba6a87c8f873351ee5750f44aa581f354d169b68cdeb5db24f4750ef384b479c096772b5d2e69dd007e712e3afe2fc1600e40180fc4e0b148c42d542c19f952d343603c022a1e8f76471d78df063f76f52d294230313237a75e41aabbd14737cdde3a4732ca833abc1b0ef5a6cdd031fc7c8cc6ce7ffa0ffae85bcd53c3936e0bc6508faed21ff7bdc19f163cb2a1f0024c3b58e85b07504d366a3bfd99895d0046cbc406c3548c4ebf8d737279363e3f059fa32bc0ebd3b8800178bf55754225b1102f8cf4c2d138b4f9b1ec2b471acec6d5d3991718b822e4647469d2a811c78a64077df2c095b37702c223932ecd73bafd1538bc55b87d29ec715db29edf7dc5c22b296d395ddd11b2d8f82dad2987260475e54223a4be6ac22291bb89ede05d11c894fc3d684bf486e9ef4532b175c6e693775b290f9f71aa1f9157a389fe7338a6a7e53e90a31d3b23223adf9e88d01dca052571072c70752863acd25bb0a2effcdd77b0ebef91d40134b3c01ce8751e3676fa0f47746c5b86f16fc73d0cf444c86471e5c9cb638b970d147add9898f29243ec5d9605cbdf6de1532a86851ee6923727bc878d3778d23e97b782b6e47a62fa78dc0416bc3b6a2ca1cca94252a50ecd756e7ef11528a4dea56a92fa14485332d23595790499aff15c6d26ceb282c4a5dce0207405c6b211ddf2af8f06f6b6c6b351df1f0a7f44173d331cb10a4c0563d9b0c401a160c3bfb8c37269aeb8b74f86d7dedd67e4e985d36ec1a6a8e4b98f7bd57f2f610d9e40c89e8d757e4bc3ee2cf60ba8d232c37342753e293f88f55918040027faf7351bf20f8b5d2caafa712796d71c25abeff3659f06d2bd2ab539ad1cd3da0d79055484ea2847da89870dcfbea84b736eff57d1c69d65e65bd2782d5f942c98c6b58cec2aec046abd07fd52726a653c9590c75693f5f3aacab5dbe137a4af95989d8e44d64a22db791d56dfadbb43d886669065ece74608bb25b8b426b9e77373b6ca157436f6f74711d825467389e48e9fc0d57e14cce93cab3520d2290a3bb43d9621f72cf9c9ecda4adaec89beadb6a747b612a902f18bd4dd539e53b7b30130f277cc0604d3c102147f9c6ab6152d13c51ab105be2853e7a8c6d943e4a8778a135ed698fd4c905f779bcb4563bbecbb94fdf45932284193bf5e51c43a9b6b9b91db49ed612dfd850dd16831bc20aad0910f99ead63f62134e8e7bb19d3bd203eccf4e645304158f23f8709d15a6335566401c02846db0b2282123c75a2b7957f6dcec8e7af644b77f3dbee0f22771186f5634a1b469a7bd92522eec381aeeef71c9b0daacd4670c87cb8081c58059281021985b80aa405e1e00f5c533901dd6153883bec9cd252bf09b980da429283083016590e7c6e3fb4f13f4af018974818e26519de317d235fc58b24d0b5cc6048f782daab3aa5e4fdb5871c9fe4178fbad665e640030d348b6f39dd00ba7c15289bb28b0b703a65e4b9fa522c8571d9a2601af3c73bc5b53a895e1095942092cf60e95020b60ceb60b15ffa469f2b2ffff5c6f92d2bcdc87ff87d3823872941990ce7c33e2e543265d7d95dd2831c57c54af9ef5317f0b18e95b555b081f6f544881ab2c5f21c3a22e451c46036193adc3bc774b7460e7a03390f77f80603deeb54c73426697cb4afffc3905cff495fbf883ba17ee09e0681445eede03021b9228ab64cbfabb4a22b4c1c198bdad91c6706864331092eb0beee59124b2ec71967631f21a3205d0409e6a4bc364e39371ec8b213f2cda2b9d242a14899eff50fef8abd1de6cab7c616bb200d0ee93fe9f9e5ae92b9026c7e1e73ed580d1675e62959b704016662288523965f30ff07ef46f3b381dd5cbd8dce11abd29c3c6f130224f00b7378a8b92dfdb795e32b79133b24403b5fd8558c53bb10913567aece968cd9eba479fef181f908da6b778b7774eac86e94038e2eb8d4d1dc962e27741f78a019e2def5ccbc2db9ff0241c582391e7bc4c1a472ebd1bdd105d389be577d7eec568d19e13717e29205308dd834930ff4bfa36dbd89ab109ffeab73f984db1dededbf15e31416902d1064a2e5158d23955eae6f803f085659f24abec9320c719acd4f89826ae9cdc869e0bda30063f908d56d7042b2f3ce13b4a727cc31f4d72a363f5f05d0aa577dffb6a8b9f4f7831de8dacd0440c35bf197ae97c16f6643badea523070c9ff201f27107bb3d1a9068186e0202ccbceb3c2ff206937d6a2bbebc2bdd3a5a47c2eafdf0622acc834a93bcb1dcc5a5129d048d47ca7022114eeefab101cb8288076aa1d9f5b69d8a75a54bf381326ad353ab67d590474e49cbade637b83c79deeca2e5aa4f70b9d09432b4ac89d580ec0a38a833254b16b5fa958e390660fd29a61495a9621d16e1494830f5beb70124c15e0f008e6e12e2141f13d877fac828451963518a564f1dfd5ac2370685c266e7fc91aaa3e7dce5744b079e36d4b03a2a4ff006a22734cc300cebbbf8b932f4f82ba3575142adb1965e9bd00259991577c2086d9abbe86de9c3b7d8dee1f9681429cb371f7da758ea91f719c3238ca7b4dc6134be825d581cd0a7d5b711f1051c32689b78b02ad70fd6167a14ff588d55250494550c5b1913f5776fcf2d969bbe3a68c41701a306109366ab6823d2e0cde9ed31cbed559d7973856fff72315e484962d3adb477616559d244ae2fd5783e6d5e9313fe27a47b66f24ccbbe5d660a337704024c1735f7c41cb0a740e24fb55dc5d268fd63f3bf1cf8110694de552409b8faa59912faae452b5e10f7c7220a5c6a45bc61c0030451b1a18fc1822c399eb7f82b4db84aa215a0b489ddc37732910e29c324a73b8a4964cfb18d75f11e29a73c7d780e527a3c9f3da156279de07d200abfbc12eaab206705fdac8a1d71eea38868008f5576d6531443b6ca65e2bc0fe3eeb970d0e77768e8935f7b668972b093b5f1b32d95b829e31f40da4c199d28249440bd5486482456f2a40966ad79a04040b8a8f99c5a096960dddb857caca88e8e646217c0408c4ab50fa88e08ec8aaa917fa0a337d1f8c1f4daf70aafbc2c647011cd6799f158d857118e829c8bbaecc73e982b187a17fc60327a9b521e42c7de2930fe60478da091f4da5231dfd1bbe762c572c83cc7031a892c307d4ba2cc2cfdbaa1073f9a2864169742a64a7b7d52734384fa78ca724884b7c4dda64df4e30856a727820f5063c38fd8bffb68ec4d635fb35317d949cf0dcb30d2faa09534b3768856b3b1aec92f252959828b975e6febc7792b73e400c662e5d2ab3bdddd732b18383aa933130ad7ae997b4ad3dc610cf73984318eaddbdd31a446337cee4c3f40fb4de238c103a51e08b12889115a635706fda879284d977d983b153c0868bb773d602f9767c20abdc0d8a385f5a7d180ab96761007d9fa4f09625f92b2c5fafc2fe741ad77c53fdf5dd50aba701e428a473c4b5f7766e51b202d1cd11aa01399789be898459b2048f65ae9f7dea91d2b4eb2619b3068d3f19df59dbfcbcb72b900aba8dfb66c0dd3942a2470199aac0f4c774a593fee754ab43c3879837e47fb3c9082d3d26d1b18c9b3923c582271da531a2dc0454fab1f9900bd2093190d9ab1b53a217a7fbd2900016d6b943f0fe8d21763957f5943a52cef65d67abd1ac11108b3ebcbdfd703858d98f1b20495047b03180862de5f0884ce51b8d24b7b59f5d0a3a855f1813f4475052c8c0caa5418314d6c2999ce0d574abc8692b4750f3ea95d47ac924c1ee4fb2b3ad821547c816b783909eae571ef1eba90de03deb1eb3b36282b0002c4d115adf05804f2435d24765a9706dd0b239608e0d4e670baf35464456ba39468a93fd7b889db3abd8b5c3cf8515c6226cf86bb8776efff56d22f2976c3d041ae9c54051b95c3f67c9e40b341683ec99980ff39dd64dc1b647aa7b587fc70f733b45114cda9014291a3389a8f7cd4444dadbbe455ed3a21bfb27f22ddba9cd20055501e971adfaadd9df4b9fce76be6bfb3c15edff116f48cc45191372e1f251e072324162f33e94060e4e01f5560a64899147e49d0c9c3aae058266361af6c780e5c0e8e9e284f5aeef6832fbe0190eb6996b53ce104ca418f184e09c74f98ddc127c61f1f732d4bf7735650617d58a75385c4cf30e2460c5340aa12bf5be0d900117f48bb8fc3c1f30d4dd4831313b3d85766a2ec63e05dada426df3e0dfbb997a830a26e57675067928e7e0280a110e3910b15832c73e2ee0a9eca4fdbc819d349734369b39e9382b2e009197b41c62a94c7ab89b34efba50c0615c83b5c592231a7a75e9dbde932db8d92f063ce7d53e7b00cee5248b26e6b9c5218e681b2b09c57d3ed528f84fd55929f3aa9206da71b8a35c97f5e6d7541fc6e966c5701a819a290d91257e8e2e34a6a01eb84232a32b2c0ffaf9b268671f336b4b9ff75c9d83cd8c9ae16173bcd95031b75831c844129b1b23e2d113979a42ef824a1a62ba57ea4ef027d61ce761864415574540bf58b193c19f8c6659853b0c84e0c8f52ecee21d558037cac6a554b51231c6665e4368479865e566c504fc0fde5ba7319a0123bfa96c2e10b879c3f5c2f60bc4b7c863476d8ccd62727a1fa03131830687367916d8594425aecb382aba84f77f3c004cfd6df1b28e0139798d632ffd48b0e4dc3d439c26c0551525c4b1fefd521a5d43b359be3997499d6572cb84bb2196b05b9c3937a677f381fed944ac3f366e4b1cb864e41ffe1498177c4a1205edd1ab5781ee54c97118c7a4e75f53dbf7f65cf629be3eb1ad28071948915d35df8dd5c2912272ec5396ea8260a50b6347f31d3a975b6a2b4fa1cb9eaad3c98daf7df7ae69399f2f1efe7741e1370908b6fb77a71e71d28bb02b883b46018f8a97bb813e22c3045bd07afdb280974c1f0d110e91d67b416f42cbfd4afebc159227d9f81f2ba1e673444e071c180a0f35686a2019ea11d3552dab8a3a271a0b1d06efaf69fb0f3c9fcb57037189486edc7624763abbb657bf01bb814998538fd8a33aad5123a8ac6be0ca7ef88e12d1b05879e9f87404418d6bc5528850e3b4c4467759fd4633f2160c04a3c6a0dec292ee76f9e9fd7f62cda03040525af3f1e81bb10f2a65cee5cf6a6bc412cc51e77c2c8494a458109b505983c994a805757487234da2d06e171b95d8dce5aa963a9b635ed64597e18d5726c827d8b5745a22d50b0c806a144c52a8ab44785b713dce884d0f429c2fc34944bd8faa252047752d813f135d24c8fb812385746f46485c4405cb9f36d6b05df79d08fe042e4f9aa7dd7089c03ac623fc1af761b30fd5eeb7943c39b533898da012acdb8925a4bda71c8dc0bef00f154e03bbfbe745701987faf7adace207dbda491914658c5f54efda19111cf3a131ca596281d3bfc630464c47bf562dfde727669517e8f6568eee3a2ffd567139778eecfff66df5234397a94777746acacd2e13f03c2f3210838d3cc647c216c2ecb428f92d02d16d665c13d43a2c5edeea39faadc357e1aace43596b043f60051726076c06b6aec6f88a418629615055b7fe7400177b5a3e8dc4d576e430a96476d1feb924da755f0a7b053d97764dc42cea61343cc0eab502bd8a5a4d486a2a767b263aa33b3839341b6dc26f9c9712c536e365920321515c7356086fc03e06099e05fb78856c15ed0639f27d747cae6275ba85c7449c97d924a98663a4272956e4ba73e529901dd1f2763fb3cfc7539839f69175f319a4e6dee3a37a0b2aa9f54231deb2844aadfd2d17ec5f279ad49f4795707c5a85b380474c1b8f5902020c47140b6d2d0b7d0f374d99cfd0b0f684c8e745b1cedc262adf963574f98803944bd8ddeaa842b6fe59e7c660288a33ab717692df779ffdcaeac20ea18afd69dd726c874a1d3e11983aa0a9cde219a19a012e224d4962618e0e1f6d33ea4d5593aeb4780ec3bb5c4fd03703be63726f6529295df8c13045cd09e4f795d2a286cf795aeb9dd16c9597f5ee8186c0c69e781c6f57bb55a359c143febd689cfd702a30e83f3432c802d19f2518a476e55f4e43b6a3b48d72aa85875e66ee47ed06000c86d10bad5cf91c7dd5cc5fa6867dd539d76d3bb1a480ca2947991f1550c36210f52698b4cde56c2c97b86367bf071594bf53bfe056a99156d4dbe265b495ba32dbfa4d159cf5d60ea73f11f79cc50ff7439021f7c8981e01aea14c89666e24a0169caec6f35b16870cefd3d90c65b956a317fea645ad53cf5b6f43c453401e6af3ee1ffc70ec378c301b49398b94f4d891c8fb915b26e8951cbf455ced7cb4fa08a03ce99601d6408ac808595378e2d3698eaa40d9115bf739e690cde90d434186514d44598b22c510d690b7a45dd17979adb3e71d0b1c8f1f921a0ad6178b487a17c87a7a5430f536d3fe4a5f4da6f548d240b0be53e8d79d08b292eef2064552f34ea71c66162cba07055f1579b9cd8df74d5e78c72ec2c3f63b11a5f69361ae750bca3a9aec58c9c136a216d6591538cc76b0648080aec132cd0e500371a8e64b7c698c26c7d197502550f9237915730643c0eaa34fce31651965f2a23b97d21037b4e12c66fc41afc233cc1218e513dbf04ef0a62b972fc5725d67e839778671360fd458ca6a24f471d291fad8fcc09a9d4da497755ce92534723f6b5d7741a3fb24d0025d10282000e0d722b52ea3745742e3f5714cef7009e90ac2098bff72baf0b0d380aee288434e004b161f032f4b478fbdf6bee5ad63d2e3b01324f99f6fb90e0e64e096c9ad28296b532ffa3c81915b03c075039a187be12974bcdef5459f1a13cf528b3db4d6797263ee24951daa347ab9ce7977e90b18a75f0814d36fcec943db0fae8ac35d3dc854d0e491141607878c0f56bb40d44490972a1272e1e4542aaf4ef52284425b8fd424b74d01542874880c47ad5c498b11bab02e5358cc528a61219542afc4acd3c786266d620e209eec6cfa5e8db5fbaa6415e793087bd8f0ff51de3ab5887572ae6f729ff624e44d124f519d63439db936512c6d119e1ed373727ed8d96f3ea0909a29313da3c7d2005417f7775926608ba9e80aceaf98413d18758c7aa09fb78bd8fc2b1e6c1d73b138129a7760685aa9b008ad79e42f3da9432ddbc712e246bfa91cc0a884b3fff579bfde9e9f9a16e65e4d2d909a804b55da2599dd185cefffe947c9893a26620495daf69155b1902df7eac5b07f908a0cc266f04f0ff9a4ccf3b102bae39b8ce3303a9a15a92ec7252d5d1375853c757df2261c788d0eb138131fc88e36fec11263b2e55fd37f165af596ac9b72da45af36cc87c83c7898959f76784f128ea0ff18e350ddad9f38aa0e25dcd8719b03ed414962094886302213b87ff9bd6a798c01ff31ed3ccc4c22c460813548497d17892098ae22eb91d38f273877f9ee5199f3072214af3d80809258e4fd537e0c23b0c5f94ff1f0dc57c1e3e42fbf92fc9ae31d59ed98eb03d16c9f5efc499effe453140e38a01a633a7642a94d27a831cb1dde82d08492a9ae6d1250ee1307c5881414b02714a7b4923c43577246e635ccba15805afec2bc493d60b9fd8d046fceb9008762ec46fb3f9f108503261b9f5b56a6d1325e2ca547b235f30ef75a8c3059e7b36156e1af8ca8617aa5ef10a7bb8b09b9ba007ee02830a1a8e8e5cab3a16a234427364d45440cdbf433ed1b81db01b22edda78361153ebe26cb8a1dc1f429a89435f39a5ea0f1a8d4b55cee9e7b7f8c4cb1e273edc13f929cf997be87d136a37116c28c2d10a199b54ee6fd2fdc0f77dad7779f46606a4c0f1ad020eca781e3544f4036f83a9281b97a757459c88621b209cc36f4e945478a3500bb9f938443c4bfb33df8b3675476305418626cf7b4ac3067cc96c002fc0ba68f448449c4335a7a4c6b59490c901cb96ede09c44fd8c6a5b9f404d1707356300c0d4bf92fa5ca0f9505171b3afac4f18ee68cd9b2ffbeab56b4b37f3dbcb611c1965a2e90c71e4f902b57cdf6855ca5a61d7230cb4c77e83f1c869cd7d88a172e484706a3eb6c0a6777fcff92bc9cf66386f4f83f8bc3c1896efa23d9eed7a8a5cf9b403e0ae7f0300191da16b1b355ce089ebce689d989919d4df1f81d74eca91a505b6a70e59e8fcba1a32c907f831da1dcfaf27fdd70e5f5e0f2a069f28caac70d60bb7b0dedc81b13813c8bd3bbe69005cbc9cb55deb8280ed6c29d246691355f7262e8cdbc6da1cccabe5b599f6a83dfe4490b4267d15be654ea1e69a04c93378faadc34e6eed3040e8cf98035e98b86746b81530f6e19eaa3bc762576e5e859b6b2fe79146f3b29bdb887585bf442fdb28d8a4e5283792a9e6b6e26cedefe4d9011f48d558ab89e23292af6cfe15b437d0e65d46739e2b37f84adf5a6b91b5df6169da21a6e110b750df3399c1fb1a6a7a998b4e1d401da1f701829410442341ed11a74ac5178c84e1288ea72ab180500fc9c0365f5cbdd313e263a16d501d3cdbae2f5fc1749b466a136ba94117f69302758a2cb3dea28d4ca8e365047fafc7714b26386a44e34649bd36c00ff9aa8e1c51584dc7f8913c8757b1b9f6f3ed43c1e64351070c3d4981aec5cbd73d89c30a90dd64bc5470b7d07fb1d68dca02daa395a121b668e7d49476ba152ec7c9f863213f7c4f5dc223853cced5e578ed2f2fc23122ff1bc6409f1a94509e33007b3c598dcf4865603b53e49dbb65328b9f77add5bd451beaa06a4bf9e011bc9d54eb524040e51b06108c0609380f5955e92495e38dc33950668ab1ad3f8879e31a9923e8e282e52fbd57330f2a8bb9c1ca95767f6011592bc3d1f05906af29569919b24b60580a45864fdd746ad0fdb03e90d441c623afa3560ca2e6181ec37b8bdd77f5d8a250e018519439666034ab3fd7fddd1f9e54c2896de3a64d39b1c114186ec2f54f3e744dc0c9eeb78a6a10e1e731ce723dfb17c79a30758ef8738480b086243ef4e3fcff9da28c25a115d30e650d942bd9b6409876a09103cc469e5cf175f44ceb5a7c13d80a1b2e296ab57e16d5f23d02c0c049ec958ee0eb9b8f7d5c18aad8c11d0147c52d1e754ba1db5d95d0ac340d3a42e8c7a708cb2c4a545d42b28b8f99852f501835dd74cb116a13e653f4d840b66bf9dd883b270e5d9d5b291180ed837d1c0d8f411d99204b76301dca703317b72d162b5f32d894d60981d0fa7eddcace3b632ecf29c6bebfd51a1dcdf808f115b1c5b27997d7848279ad7736a6a94e48b16b4f8e0b65ba0b3b53294ee4e9e9a470853e9e50fde5e035967226f20f503257b60ec7548713191ec1ad7c086757030853749a08df2dd05d4839e02737171d96ea6b71d42c8fd3eb3f9ec8aeda19e7c75093a778fc4cb1ada6d8c43ab64f870e9116671c629c7d8e253a409c838204a594027bc49a53bd4cc66896939f8ef403c67cd9627089436b636e4e8293dd58858ca8200a14e1de9d2cb24769a820aaef19ad85515eac32d1ab6158893bf0dd9aa36725b8ee56e33187cd6bd26f24c5dc885febf0d1afee785cfa4b128f7842788c6c8f9755009e2f576dfff9d3346381fc4ea63a7076ae239fb84943dc3095e97820a5639a091f5da8d0844abb457565fda1a30502c563d546381b0d77cd7665a24965ab2ea1ec8d4c30ca9970dba223e1112e8a5f39a5d6d123bcfe077e2d6a57f1be8e8a31e0840c70a5dd074bc38cbfc3450ff77afe9216d3834e4dc6ce8c58889d1475ec7db75312eac5ccbbbae08dfc2675ede9f27f90db804f7e185bc143e132585f9c0d39d2892f1f2215297d01edddadfad6d122918433aede6e2458686ae7c33583d21978fcef91a76f12759efdd5c212f6f9492fa07139414a657fb7d4c8fc66481382af0d0af87847e8dcd38a1aff437b9b179b1f18a269cb69fca7a32cdd14f3c23ac4a971a9ef56105baa6ad1edac5ed82e742e191e4e91dcf962d625a1dbda462ee2210583c0829f38a54e52a8908339699c6c123817d4c7c0bb17c0a1fb4fb35283d931a50bc581d365faa3cc46a9f2e1e6a92f96daa88d93950e2b07a8937cb53dbe8958dd3f9708d50d702d826d21a926fb8a19eaf1cb3226460122a5367fd6053d62483e1ada18e886c0a83cc4b7ccbbb756e495776cf4522d5bc5cf7d82555bf40e797ec8bfdb2c65a232053eb3f52a36b4982e758f0a668d0787e651e4f45b9d5dbfd7ad7f1a739e9eb00b420770bf3bf132eeebdb12e4aee2909502ecfa25fd22251d08da93262d40f5cda60a1e601299c68c88b520116883c0b881c3c84ce2a181061cdb2650fbc26a0ed62e8255b717e721a0e6fa8ad834f05fd79ea83b1d213d52507680a9f945984aba8a13dfbb059412ffac2364580decb54c65bfde6e37a32759d4b619ea58ba60e837f35f56330476898fdb16170f5a8dc05b04adece995353242abc766ec272f5d272578d249bf5aebc1e97769a9db0f9eb3df86134d74ee06be3d8fa46e323910bab78312f620acc5ec081016fd4f4d9ca03c4ccb82c60482a66df2b757822e6bb4fa9061e6a787c7204bcb084b9b55ea64e8cc9a288fab762713b77bd0ff33b79bf1d15aee995db9aa9d5c25b8f9bc2a23446442ca3d58128ec89117608173406488945a08688573ee885f74c8fce73f1d39942728febfcda2a255872c68c8138018e0ea177895054524cce90b90817992d73037179bdbfb64a72dd58e41e0132af6cabffa23d2cc9d108e4eed7981205dab846f04b5d322f63b19779866958c53b433d4afa26e488b84a7975b4bf3000a2457352d84b45d81a34c25d68a8bd3ab66e242f493ca36be650ab862168f9203e8c6e6598868f218b2e66747e694c3d69537b5f23c1610545b2931038bc264ca919d18305d5f7462e1cb51af4b58d224cf2dcc6e3963f353878f9e7f16f0c2a99984d817b52bb9a2ae69da629a16e006f3584a7e4ec2e7497a0c531d36c6aa60188117941093c5bbcafc0a0c3bf92d8ee9c1f37d1cacfb2140b38f202e097dc8f46448e7e4a9a1439b9f6b5d44e9160a9760b0e42ea85c731345490e7e49c378e5062a451c0292cb50d48545f1c7383cac3fd37df07192566807a30959a506c17adb8f7208ccfef04c1ffc1932b63fbbaf821a0d1790a19060230c77dd9bc7e176c9a6e0ac13a0d1c333d3366ad17b104d60247930a4f43d3c8521469bebe7b4362a4f2eb3793f0085add75416a0f5eb10f3cca524aff763fe484383819f2c967a9e97d4755669089c4fd8cac803bcddf58adf0896ff4abe39ecbf8d272e9e4f8e7ec77bf755a3780b460b8432fa58bd382175da8c7d87a4aedbf5e0c35f97bec5179529dc02cc595e32bb0e83c22cd91321a60ceb7ee70d0704624883565d51cfe7938a58d3a8119b38c62619d213f0dcf88d1eac7c915b2a02ab77bcb462e02ed5d903058d743130dd8089df2f1da54285debd0d35b6358e60ed249c9b49197ba033ddd8a66c716f440561fb44f94ff363456dd9d47fc418794a97351a2fa9e981d9b1145cbd002ae5906cfcc53e0e1467c245abb992c8fcf1c927ea64655f838330571d568966c40956aa2441391fc08397f22bb4bfd0ce0768349ce18304f7d3c6d90e4440011bb2e71ce8df8410914b8798b4c86dd3a2a4710bbe5a7ab1ed07bf1c90f30d9f78ed3536297150b47467123e9889dcc100c347879724b708e8b0851bf0cd9e3b760df06da95a4732fb019176f8550e94ccf633f509e54de6f62e19a20e14e0d7c3dfc1c6accc9c78e9bf97902bc11f1cda63626dddf32285f7455db99c23b447074a14fa65589e91ae42670e92681e591a000002a55f21edb5cc47a7561838d0a8a32923e4bc0ba47d0940d7e24dcc3b35f16b5e7838ae29783800b1fabc4c6728477df3c8e27bc43b11681f016a418b2d30f876444084f369e70ec3492bd09abcab082fd72f2a7591d8e9ee7fd9e01757703af3188404c2f8db22fb41ec225905feee5b08b7b4578e4e564e8de5c87df889d0acc02031a30d224d1fdcb969bad9eed19387d76e7169753e9a48c1ed37441061239966a05741ed4b32a4533061159b79e0ac205d9689eed23f9447c67b28a98dd5acedf14be9825cfab0112bba2c4ae9a185b67acab9f95054812371e6ae356ec6bf847d828728f42f51546182b93581bd22b03d2a9d9a041c0a1a75233c72c159a2f45314392b29e38291f20d63834216092ebc90feebe3ebbdf4032d7511685e4811840b91e3665310baf4c8cdeee47f23ffc6337bc64c270625e970524fb94cf05ab39f0c356ef91c140116a77dd986d8f492b22ce4ea02ffd243c1d907927f5a978a91ec91818317946f460d14a2b29db8de287b3f452446bbec01763bed6f202fde250d995d47d58fdd73ed1e06e576accaa31b9111474a436e18944a2ef11987122e508de2932c44193809fe9867eb1b282448cd0395fa798dc2f78f06ebd040c06215d20556273c3efe892d1f03261543da204f74baef5e70d442d91d23044fedf93bae9eb5ff8cfb940326ec162f5d774956253defbb0f5f885ff38c6ae9fe865c053c4d23f14ea285638c1ced2639f05dcf4c382cb9a675f47e5e686cfa47073f93104689edb2061cd26c83461bbbf735b29268143b12aecb4ce7ade1d3b4462fb0e4c69faaa95b555df8973177b498a7fa808f74cb0dd65543f10c3c470d8c718bbd4cc57d54017016a7673e63777dbe051d4f193346d5e870f4ac64c1b90d0a0ce0155943d9d69925ef53bb7580891670f3acb34dbbf787c544b8555c0aad0465f291d2fb1f8cdfdaf9bb5a0ff00c6047ade89f7c2d87c97483fb944009dfe293a8a415079e02b46621fb174d3aae18d0e9addc1feead3d6dfb2c98a68ff010edba25e07f8727252dc453aedcf5cc831021dd350913b96799ad8bc6d5228a693860baf698c996213f82ed57136c98690dcd88f0448b8562cbe7ac1c958c885e4a9d1977a2944726f401dd09288d2a40f553413149bbdf51a1070343eba49c0b1691021cfe1d80ed7b643ef06309ca7036b224ba36977a12b822973f0b5f8ad65b3fe2ed9cdbfe8015c6bfacfcaef296432f1aeba7efee61593775cd97bdd09674f42c418b6e8b2f31a9a1d0b20153f7fc0253de7dd2b8ba73d09d9d1308b3c286ddde5ac925f66d0f795c2015e04d5278d913242ccfb639e061c4218a47db4bca9eb5b5d6342b5b75a9c7544de6819d21e0294f6d91066c6755cab0fdd75f5b9a60f32a15b278b70a7024ed58af55b652eb9dcf9289db3ad6632d50abbd162a3a0f4907ae9ed889cce63fda2d44d3e15c2bd4ff2ec96a796d1ec5982cf42171daac0065c9d79d1202bc28f9431f844ea293c370ebbaee7d67d15296ca4114a6f5f5fbdc25328967e486614b0ed06793eae2ba66c71ee0b1e7694ec5d2b2430ceaa2adedf0d7ed6b41cf0e4c1aca94c68e9698695e9d39266ec551eb57261168867f5ac4f05b837798f45ae17698e6e7771f0f6db5acd9eb32127e09a13ffef3f253b2586f7a16dacf4868528a94e304aa68d946a85c5357a3536c298bbaabbba4726b346582f0c0c0caefef9f8aa8e8082bc1d3e00fe5e0dd5bc32f343b2a710929cb005750c802bba94646ff90afeb923577f1cb9c18da7cd9c8cdea2f98256e63f5d629cea6de70b5e3ed8a31b1284cb6755217fa7a38e6caf87e2a7a3d1d454e9b52b64b182f0d1c9734434dc904aca43149f908dd877199c62cc9cd2f1106b1fbafc79da8932c9e6ccb77bfb622848d6571d5acf330285a08ff7e51effebc919b8e9d1e3150e9663f492bd19788a6d7d96248deaa467c316bc4e7ff479f5a5d0e289756a56d864f83cd72ab47d8cd38d876c0255b44abb13b8ecc572c8c786e455f11f1ac779f5729604918de14cf2b7e6f883dd1f98d7710cd5021809b1ddf2aef6ea79d0bc03296849bbb4372c5a035fbd6a7f6c48b9994e108be87cec9c63cc4f55ad98541522a891722fcb4d2f7b30e16ee279344deaf9b0cde84aa6eb7fadba3ffa3d088b97afb263c7ad585a912fe7cd9cd504162e18b11bf9ec352e37eab97274d24e71dcd78f126b46a6f01f8c0b8f5022623a99b99f7028784752682267f7f170ff8ae5c591ae381487cf030b1901a742dd2c6f4e98726284084ef35d85f508734ac39ca04ff6d2680a5f992da0171e9cd552d15cc16d108c1958bba538bae3477d6dd61e9a19d67ee992e610418f12fa7d38183b21ad57b8a02de244e17f6db6601b90d6d304537240219711e56a409bc91c4581ffc9c38506344ca95849edaee801cbb842d854cd74c430000268b185aefcae81c5a9fb5c2b7c88675ed7bf5b96e70f89aff0bb0183e7b420d6d3942987c58512eb2d716f60456303798b09b2873c75941921ca1a11da316507ed714411827b372bb3f0c3818a5f6cf1352f9590f33d00624fb8dbc80c009954cf7c8492b63cd753843c96b057e4e28d03d1d4d60de851d90ed92be47fcf82c7b21d3e9fd05689c4fbfa3082cfb057fd16c1c2c229449187319d7c8b2a9fda8adb7888e17bb59fb0c9ff77563951739cfeb789aba049729081c696e9dfd85e1d99af7a214c7cd11e7fcdbd7657f466d4d51fc866dc51d6a0f987733e5637ce9f655d042fd78ed863934028e0871b4af990a35ddffd16550ab7c1d8ed2b8eadacd05744a4c8fd0e495c1320380aa60e05ec31c58470031f33a607a3b7f9f4c6fb68f3a8509006dfe47ac01a30e7fc0a4f15e8dc04840c688c0e8e69cf367b5fd7b5ca6745d7f77a4fa847327f2dc552a036b054e6673450b47eccfa08586594a8168e8b71701bb4c4d7186d9e344c50ceadec523f38a7e21ed8b19465e0ecdedc9a57238900eae72c90a4189e008ca2151de2520baa35054d98c0ceb2f775e94e2a490101af07ef8003e9d5422cdba82012b5513caeb6bf115ad249ff53502698656606b2f4a05d8c02b16c4e35b48e27fe6ca84e60bc2c644fae9573cd9a46008e87fde08f9f74c32234bade8dec56aad77fb05245bf78a7b8279652a03e64f376a02c782cc9efec06cdeb3ed886ccefd67f03b651dc2c922c1bfa88c383a7f4222b4c8ca7ab8e36692baceb3930ae0276307e82273306d8a762ab403b771fa98f214e264adc2790cea25445487a04a36b9aa3a9910a5a69d63634ba1505d3bbcd26ec72c16a0e8a1817b934851a613b5c18bc4bb3bb22ea29370358c7dab8f1deec1c90e20df67ae23abd572f44daaa00a976102307fb8d47981351d136936c1edcb07408bfc725cb88b31e967baf413b91fef563566d075b4afe729d4d3e49a4ded64993c9b715bb0c4e8902979ee9453395b3aab579ad42930d02cd462b57db3afdb7405264951bb5c837fa071efebfee9dc505e883de7a8d747bafe842d554a94e189684a7d8f513bcd2999334fb3cafd165c65b5fee346dc7e5303d246f604be2de27b6dc371eaad394e315ab23d3a1c99ef1b1ee8a2195a6f34fb69aef854544203d43619b7bccfa7c34948c4ed35c79130fe20ad519c742ae6b1a2ab0e3ac56ef0bfa8f0394abcb1fda2bccfe909a355a26da34b5728dd26cb057b9971cccec6035e38ae5259e9d2145e1f79b28d6d73da05dee3af2fb06e0e0fee657e4432e12b526cab500c2a06ec0927ef35459ac5966c9816880295b606ac889b1f3776aa83fe1d44a97f247e60616892b6c5deb6b0b832b8bcc626a181a283b6b5c2d170e8181ac9628bd9c30c3b0988af560ffc09b5dfeb9995d7eb7e06f423aea761bac52a81b1df9e7de76e5cc5996e39f5140b32da838b7ea54d30f9949f7a38a83724101353ffbf97540f518978ff060f5fe633ba470f02c52a0e1294cc735d4ec9d2c474f8389aafbee34a040e3f6ea4a748a8c2ccc84780b0d00ecd429e98920d36fdc2d071ee3c13e5200404ab0429168dafee9cd364256587aa3ddc526b9c9a1aac77c960c9ca9143bf61dbfaa1fd109ff61c03c3e031113707732723ffde91bfa17c378be3dc94d795906c649a07a08934f34d6331d242586027d82800f554cab2417ef8e43d4780fe8bc6b09ca682df922bdcfbe3b41612564130c9e77ba8cb3b7155b2281e21615517a6586fb6b664171df9b8e3d7ac00f85f75240bde6a35c293863d1052b34dfa67f7f743507e8423c2df8a4feb7100d0ef2149938ee12d48369cf9cb6e3ab4dee0026f54cafc2e71d142be3c4f227f51de2424a61c79bda8acc78f55bce007311a3af25f85376d5622dc746be72e0502fbd5fe6c7805c6d05e238fa29aa36ca1880848b946e1c36cfd9868e9c7d35ca39f7aef16c4d0d84452047fb964d347dac6db3ca91ad1fe7fe99e2d42648b20e7c45739d787c148c3cfb212959a3a41781b3ac513760c27c704c9642939fbe2662a7aeb0cb5c547db3e155868ea1d66e5fc0a5c8db514911f3d4ab627d7fa3c5d7d8b0e6af03a2b439d2c8e1ef34aaed8d558e1c9a45ec04092d08918a62b2f642a032fac8f1fdcf68f31d0228c6f2dd029544a7a366c4a6f637815a88a33a947eb20bb5cd6a8df589566abf0eb35f5b9bfc6d379536e91448f8e53c206ed205213cd34ce90b416c93c6a595466b02710b96a4cc38e5f06e85af889e658376af6c02bd23b95e0b55a07011e6a3a86b8120fc7f4ff80e9406e76773e7a293723a0c51b0745978555a0f3bc3949fc44648b081c6a46acdee152b8a2fd646ac9ce4f1a3fb76180be1c18c8066312ac76e946b8c06eaebc6972c9ba2ea4b8cd33e99db6b8c419c352c49937762aa12bf6a74f15c926c639d7463ad4ba11e20041fb68dc1f13efd8ec50ef5fa8017a7976c3b9912047d371b5c43b35910b3494728b0871320017530d45d5701fa364306fe7d4a26b380b2b6dddbd30c6384f25f3091282d22862d8e9c9d23ba39d02aaaa13a5d157538297f2cff1428040b2dec8c49779fefe73b225aaacf3b1f9d8e33c933c77619c3ddac5b4906f142249753f29f09934b23a529270a7ed133ad7a060635a07fb6c618452416522812e62270fe11c02d804d19e413dce77cf4120af891c673296a094f356055f0a122356260f4c477bf18cc0fd34273905525d988e6706d55f1e2529dafe8ed3c20f47db6690662f7e7f2c01b030678b8d62afaf5bb878c0c1ba1999e585e5ec1b03a15d493333040ba4300e82bf46baf62fe2312c12a1a77335129df701522df3bfdd7f00c7ba6ade6a04ae09bd86c8a7ef73fdc5a2cf6fd5bfbbe4375eba02a38c17093afb38078b71cb6cb43e9fa53689bd011a3d6ea27fddcf6a1305987f9d38300f101020ee9bfdba92bc9c0dc7132b934c087ee97530db5814a2ee706a56bb62314c6d3a5387ff8310ca1c6cb36d18c4f077a64e833148591a5d3c2a148ae56d41cfebc88f5cdcdd98acf0179b1cfb264bed7e0439820003662786daf298e7a175e4167a828007aab1f445e7c3e2caeae50beb74fe06cb07ea8c6d81dc15f9ef13e771cc189ab8df8de2b77d04b69f0599bb4c875be1ccde292289edcd7fa3739e702f58140e2ee90e94f98afe792e6760600b1577cf8a167b1dcfb78c8261b953fb1dd2347aac1c1ea68f5006ca853e85f28d1a17ca7040e0d8d0fe3941373bc8b11566a13a56c09acda4f56c5e841d631bdaac68abc6bd4089af0a2d9e1e08aeef78c29ff842d673f1ba9997151315ad85cfd049858afec2e33e1bdb79beac12743655a08e4293b72e4aa1a2a93d66ab39c804d25d7ccce583bd824b8f5e43c05ac3f0d422f1a9f1595b39802efea3e7ec5da67b5d91414f0cd00d83d60b1be92cc709f6c0cfca78d5d314b8c13e5ca5272b68120fd7119e8a4da203a3475535354e0648ac29498bb3cf48a31e2cd60e1e8aefd28f1c75c95298bf5b3b4cf9a7994794f3f6759d395deaaeaca4b8b60c9b2ffb9431a648677b6230d5c9421a07920db64a9a4ddb571df6cb0702de6c2f3f176bfdb4b0f16865bcfc3a8d8a4d8480f6539c18740fe3313b3356597ee13d7ebc6896aaa1d22f4cee60d629f29e17195cab4eb445fd84ac4a90c512894badf44f17fe20512c556c2ede4323bce0083d92c365fea162d67ec68b1fcf716828decce3b86fd2de4484939cc1b4247e3f7a96c139812338968f882180d046b45230ede2159ef2d9d7d549f000910467e3b89bde4552e45fac880c3eb11257238ab8e8f49f073866fe3991cf519e99881c6f9292451f024ea975f19ef0545da4f68710f2114e9b4fb75b26a23c3ed7b672a101782fe1b65363b6ade1142e813e07ce2deefb835fe058c86dc2d5ca84d140aaf01036bbf77d56e793b970d27e16bb1e7a6b1b6ccc636366bcb1c63e7de2cf12cd3ec83da831f77f8bc3319bd0668d940de81a0a7edd57e74666010e95c6c0e36fedab4cbbecc1d7f8045d92a32490791ed6ec7bf1429cfb6dd34e1d38839cb5e39620e2a78fc7459a5c5c2dc18764431399139ccd51066a70ecc6b982049d4c2c87877a6a0c23a4fd89529adb49de9761a44475cc1cb599225ad44dfed4ed6d0afd51fb578f0f6225b510a2ed04f01447be1c18ddc5795892af0e3e72389ed722a106b26bcdac7f0645594ebd112d31e0677b5d7463b87ccef1acc13e9a6ad0d1f7d0fd2242b8ead65f9b292238703c2d399f40a370b4050385a55c0a3c7a7093d5c7ae9727e24c93dcc3a3cae4fc3b194672c15e5971f2e196a9964343ec5b39da26b52def12395908dd56ed72a22add1b1d53b945a245cd51b746fb811ba2bbf1a41aa9348fe28c5ac3d28ca098937ff2ae456cb68278dcd45778b4d0e389f5cbc37a54e6a7ba28c8bce97affc3d82f8d599508235877b0037d269f6abbef2b299607cbc167c2f16d8667783fe9413bc11892a8afc71114c100d8415548ee568893b01a754868f429dbe520d6ac48f1640d3c06c831357a5f33034545025f2425b590117259d2b2a1c4d839dea0f81cee1ba39848274cab9011a61dcc7b6b0e93a3dfead62ddac1a6dfd5f8892b13c576620ac906966da84e4df985a8e43e013a12448b042e31b6bb923199a8dfb4fbe4d99353380c98dabea8aa6abeb47d70170d4b184a5f9cd4fe11f1b1f3da393532047996fdcd4df663dc81f4b8d915e0b673cfdb3cbe8720e7ae594c9382b39f9ce653f3caf6da8e50cb23654c7c8f2ff6d4378ce04de1cc9fd64bfd040a459877bd379a171056cb7d43f02bb005e3acd2783f7420e657cb3e76bc41416710c760ee44e4beda13438d9f0dcf8454b5506162e9fdb3e4df139f453192a98b2398b1db8fcc6019cee6cc53227376c6cfafb38301bf22e4538c5913a46e3805de852e4fb1fa7bfe33b6f6873f470210415d9f7b97a22d8abbc12b1f9abfddc61a3a6c01d5c3a632d345f96af6f704d99c3557f9f6b9c6c0e5a9b4a1a0152bad4ffa289c5688cbe27e5a81731c810dc2c9ea3d7428e3f926c5550287328ee8ded944ebd1b629732a62f3037741d222e06f08589aa23524d665bd8c62882d9aa3ab81ff1c1278830d474287237911836da56a88ecb23a57fc84f952ecfa0ab382526232d44e0025e71b168688387cef036ee9c2340a9a3eb8397e8d1db541ae3bf47651609a07719ac9a88b86e9f4ed00ecdeb051f7f3651a7334d3c726a8a393748fdf76afd4c22df4af33a50beafc7606cbb42aef23de7e7beeac31d68e50736fdce648305204dff2238cb6e8a94056204f6886083b73ae513d695c1019d508a58515a59a99ac9a5f7449de04e09548116ee730fc30d806188d291d3dfffb5dbb79bba09c970f44b2be4496e5e059deb8bc8963ec769e4721b536b870249ab9efa562629c04ab94343cbaaf17ba7a8cfca92832ce56e9edaeb0e0d3e880e93386b46cced3a901818a4ed29aef8695b9d3a2f406c4c26e8ea791326ec5177f3e74a93d0baa2427787504f3b52fe51e35b75dba9e22333f484a2a75e638f110b4e32f6c8ab220ae99fb073d1c1376c0cab8dce19be2fbec85f0184e49efdb2c4f2ca2398b0f60bbd4417d0283842c14c28f44f9f3f7829aeebed2fd69b4c084b897d9d5099c3bda20867531c4e161e20aaa161109189ebc525593479e8171ed78b441ccb9a6be089ec375e58141f0becc4744fa5008b9a647dfedb66b9305b53718b7199605cb7df1cf6435135db1c3ea0ed93b2b52540faaaa2a2a81b1fe851f14449aa03e3d9a9ef2228256abef63ab52792740ca7435995b4bd6ac4c6e71d2be1d4d6e9a849bb526551fd5ccf7bc29b8c0d58a1a7bef6d3a5d66fb0a891eb23e64505b511910623a468a8d9ddedc41cca1f564bb53bcc725aa5f3159464aad2486282a7bbae9fe3b907294dd6de423a8325367fe9a9458d2469368a66cb60532616ccb4ace7df948f793db418a75175e4769daccf3b2d81f82cbd7470fa745e6e9636dd6909cec31455d87be9870da3440a5643ee31546fddc5abad84b59084804a5900f0d85ae413921fac09a84044cb5cdb80f486f8f6b46c65d0eab4d7b9c3fb78301cd3f200b4a5d4391d34fcd84d49b90a2f1565e50410ec290bec2559799a224a1715a648af5cc358c8e4e5108fcca04bbd9f5539f4648af9d5b1684226bc5e5c4d3e584e9f7c9a9a3a29c3a45010189467a756acd66bc59a70c2c55fb0fec4b744e708a65295cbe4be62399ce36f32b75d8d4aedf7fe7b7947bd6b3e2a8eaad9fdb05ab23d65980191cb88e4ab7df6cdd16a085860548773b34d95a8213710de303fb0b8122309c9eadb68b907ca655b027c03381adecb507cc56a50ecd1f5a243d45e789be265cfe239cbba3b353d51b2824d305b29f5928f816104e05bad84fc8a91d60387e4026ffa27afdefe49da2efb7e33117c398e540dbe4529df5f3d22ae2c6d108654e02d10fabcbd8ccff45faea59e3abf01c4b5394df627e397597486a36ca7ce7167bf3d8eb7426ffbdda1cfac5a986a97462ee1802da50a199f15b8dfc77d52aa1a00f4efed4db2ca0c8da18df2bf8a28558d0015d2574a72ab81588c1988720cb436c1ada2f19ffda531a5d5b7d9253530c7f9e4e3e1e15882e32607a70d4f2395936a65a9fd5d741f1dc666956bab6621cd4971ff4f1abee5d0ac44461bf39e473f7152ab31da55f333cf5efea3688963c2e3a70385de7c9e95cac0ebd45ce4a87a043377023cd326d46752b27b1f4e83ce6e6de8b847b4006e7edf863a8022aa5a977f5cf396a6494ace8d7c73f212bd497a3cf7193e9bdf0a334162975217a4e3a8aa8b67f0a61523154eacd4171ff0f1cbb4ca721f7b387e6083fab072316783a8eae53bc25ca58c0d33c6859c8057d90d9fe757d144bcf2c1d9ccbb5bb88b7dab841e3a34ca21edc6d1928a74f68e4de51e739a38dc233be7f18d43f9cf225b3f079d7e6259aeccc7023e1cf4b774305b81bd0f342735a60a3f8ed16450835af0b1da3d64233a41331d65c74b7dc3fb37fa92b1e7651c7ee7db096584a09d3c40f3a2c43b3388d4db089a9d0d1faacd528edffefd1df9e292a3e01314b3d9c6f8f3f9e336d367573a6a728a109e670c1f290b614cf479a2362d4baad2a70cb5315ead7294f6665540ebbfdd6baa53fab92784454f3decef91ee6986a64e2af9e6fc181d3a1a1a8c0236b53a0fe0cfbcd0377db573ca64b0efc35baa5ff74bbf2108e935a638159e63bffeaf56bf0d4808c9eaf07462d2368bc4492211a21e66e3fbf9322038084bd3df04cc26aa34e3bb7633188fd7982652d953188c1f8fd8f62a4f0364c2e4bdfcff173e8396aad204d9943f3be7c89e07da20e2ea9f5efc1bb7f3aea3afcf2d48cedeccf3352d1da6739cf700fa41da9d2d6e7a1d386f6937a1bd2cece80fac4e8648d35f16eb824dc6e18c09c87456be07ab2adf09dcb4030dffab1718d9ccbb30f32c4c0c505620cae9140d77c0e3a3e6f74b9c3e0075686163f69a3a6b2f611809eaf0a6e6aa73315d56b256afa0926bb6e4dd8faf0fd08d2b9be58ea2b7be91d1a3a4f215b2409b4cf9c02fbb38b034e4ccbc3f5bbfc09ed032c8c0fe8f081f446544ea178a5abb46bcb3172b28a95ed30dfcaa3f4f2b3f1978647d9894b5f227f00a41aaff529dcdb724756a54f72e5071ab4f2152c8e52f565add9c4cfef917f96aa11b6293914e911de0fbf6614862f253a63dcb506802ab0d259c0bddc47ed3cf95be30b4f17e4e80ded8bcf861ff4dc7c7206fab121648593d4257490098a47a2df911b3363946362206027085cf8c12b2af65b93d067aa0114f21246951d94095a0c10d982ec6091a0a726d12210068c04f874ac871d291d7d235f7be9ee5558ea4d5c4a0968c88ad30f3a09e4454e06cfa699a0907062ba11\n \n \n \n \n 您好, 这里需要密码.\n \n \n \n \n \n \n \n\n","categories":["教程"],"tags":["Linux","shell"]}]