Processing math: 10%

المپدیا

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

ابزار کاربر

ابزار سایت


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

Xor

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

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

اگر ‎xk‎ برابر باشد با رشته ای که از ‎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)‎می‌ماند.


ابزار صفحه