المپدیا

دانش‌نامه‌ی المپیاد کامپیوتر ایران

ابزار کاربر

ابزار سایت


سوالات المپیاد:متفرقه:آزمون های اینترنتی ۸۹ تا ۹۱:سوال ۵۵

Xor

شما در صورتی از این سوال نمره کسب می‌کنید که به همه تست ها پاسخ درست بدهید.

‎‎ رشته ‎$x$‎ و ‎$y$‎ به طول ‎$n$‎ از اعداد ‎0‎ و ‎1‎ به شما داده شده است‎.‎

اگر ‎$x_k$‎ برابر باشد با رشته ای که از ‎$k$‎ بار cyclic shift right خوردن ‎$x$‎ ساخته می شود، شما باید به دست بیاورید آیا دو عدد ‎$0 \leq i‎ و ‎j \leq n-1$‎ وجود دارند طوری ‎$x_i \oplus x_j = y$‎ یا نه ؟‎‎

ورودي

در سطر اول رشته ‎$y$‎ و در سطر دوم رشته ‎$x$‎ آمده است. هر رشته از حداکثر ‎$5000$‎ کاراکتر ساخته شده و اندازه دو رشته برابر است‎.‎ ‎

خروجي

با توجه به پاسخ سوال در خروجی رشته Yes‎ یا No را چاپ کنید‎.‎ ‎

محدودیت‌ها

  • محدودیت زمان: ۴ ثانیه
  • محدودیت حافظه: ۲۵۶ مگابایت

ورودي و خروجي نمونه

ورودي نمونه خروجي نمونه
11111
10101
‎No‎
‎11110‎
‎10101‎
‎Yes

پاسخ

اگر ‎$x_i \oplus x_j=y$‎ باشد و هر ‎$2$‎ طرف را با ‎$x_i$ XOR‎ کنیم داریم ‎$y \oplus x_i=x_j$‎. یعنی اگر ‎$x_i$‎ را داشته باشیم مقدار ‎$k$‎ با شرط اینکه در رابطه‌ی ‎$x_i \oplus k=y$‎ صدق کند به طور یکتا به‌دست می‌آید. کافیست بین تمام شیفت‌های دوری از رشته اصلی مقدار ‎$k$‎ را جستجو کنیم. اگر ‎$x_j$‎ برابر با آن بود که ‎$x_j‎و ‎x_i$‎ جواب مسئله است و اگر هیچ ‎$x_j$‎ برابر با ‎$k$‎ نبود آنگاه ‎$x_i$‎ نمی تواند در جواب باشد‎.‎

پس به ازای تمام ‎$i$‎ ها از ‎$1$‎ تا ‎$n$‎ مقدار ‎$y \oplus x_i$‎ را بین تمام شیفت‌های دوری اعداد جستجو می کنیم و اگر ‎$x_j$‎ یافت شد که ‎$y \oplus x_i=x_j$‎ در آن‌صورت ‎$x_j‎و ‎x_i$‎ را به عنوان جواب چاپ کرده و اگر تا آخر هیچ جوابی پیدا نشد، مسئله جواب ندارد.

‎$y \oplus x_i$‎ را می‌توان از ‎$O(n)$‎ محاسبه کرد. این مقدار (یک رشته ‎$n$‎‎ بیتی) را ‎$k$‎ می‌نامیم. برای ‎search‎ آن در بین ‎$n$‎ رشته (که هر کدام ‎$n$‎ بیت دارند)‌ اگر بخواهیم از روش بدیهی مقایسه بیت به بیت استفاده کنیم برنامه بیش‌تر از حد مجاز زمان،‌ طول می‌کشد. بدین منظور از ‎hash‎ استفاده می‌کنیم. یعنی به هر رشته ‎$n$‎ بیتی یک عدد نسبت می‌دهیم. پس کافیست رشته ‎$n$‎ بیتی ‎$k$‎ را hash‎ کنیم $O(n)$‎ و آن را در بین مقادیر ‎hash‎ اعداد ورودی (که ابتدا یک بار حساب کردیم و ذخیره کردیم) جستجو کنیم ‎$O(n)$‎. برای اطمینان از صحت جواب به ازای هر بار که ‎hash‎ دو رشته با هم برابر بود ‎$n$‎ بیت ‎$2$‎ رشته را کاملا با هم مقایسه کرده تا از برابری انها مطمئن شویم. اگر تابع hash‎ ما خوب باشد تعداد بارهایی که به اشتباه ‎hash‎ دو رشته با هم برابر می شود کم است و اولین‌باری که به درستی این اتفاق بیفتد برنامه تمام می‌شود. پس اگر تابع hash‎ ما خوب باشد به ازای یک ‎$i$‎ خاص تقریبا از ‎$O(n)$‎هزینه می‌کنیم. پس در کل زمان برنامه از ‎$O(n^2)$‎ است‎.‎

برای ‎hash‎ یک رشته ‎$n$‎ بیتی از ‎$0$و$1$‎ کافیست باقی‌مانده ‎$\sum_{i=0}^{n-1}a_i\times 2^i$‎بر ‎$P$ (یک عدد اول بزرگ) محاسبه کنیم. برای این کار در مرحله ‎$i$‎ ام ‎$2^i \mod P$‎ را در ‎$a_i$‎ ضرب کرده و با مقادیر قبلی جمع می‌کینم و باقی‌مانده به ‎$P$‎ حاصل جمع را نگه می‌داریم.این کار به ازای هر رشته ‎$n$‎ بیتی از ‎$O(n)$‎ زمان می‌برد و چون کلا ‎$O(n)$‎رشته را ‎hash‎ می‌کنیم پس زمان برنامه همان ‎$O(n^2)$‎می‌ماند.


ابزار صفحه