Для решения задания MS15 необходимо, чтобы предыдущее уже было сделанным, однако на момент публикации оно таковым не является, потому данная запись содержит и его решение тоже.
Условие задачи MS14.
Зашифруйте текст из входного потока заменяя каждый символ по формуле [latex]c=at+b \mod 256[/latex], где [latex]t[/latex] — символ открытого текста, [latex]c[/latex] — символ зашифрованного текста, [latex]a[/latex], [latex]b[/latex] — произвольные ключи (параметры) шифрования.
Входные данные:
Два ключа через пробел и, через ещё один пробел, текст.
Выходные данные:
Зашифрованный текст.
Тесты.
№ |
Входные данные |
Выходные данные |
|
[latex]a[/latex] |
[latex]b[/latex] |
Исходный текст |
Зашифрованный текст |
1 |
f |
n |
Kittens |
P▲D*ж.ж.м(B,@. |
2 |
4 |
j |
Hello, world! |
◙☼ю¶z▬z▬ў▬z○ъ♠ц↑ў▬т↨z▬║¶▲• |
3 |
? |
. |
0123456789 |
■♂=♀|♀╗♀·♀9♪x♪╖♪ў♪5♫ |
Код на С++
|
#include <iostream> using namespace std; int main() { unsigned char c, a, b; scanf("%c", &a); //Первый ключ scanf("%c", &c); //Пробел scanf("%c", &b); //Второй ключ scanf("%c", &c); //Пробел while (EOF != scanf("%c", &c)) //Пока не кончатся входные данные { printf("%c", (c*a+b)%256); printf("%c", (c*a+b)/256); } return 0; } |
Код на Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
import java.util.*; import java.math.*; class Main { public static void main (String[] args) { Scanner in = new Scanner(System.in); in.useDelimiter(""); //Чтение по одному символу. int a = (int)in.next().charAt(0); //Первый ключ int c = (int)in.next().charAt(0); //Пробел int b = (int)in.next().charAt(0); //Второй ключ c = (int)in.next().charAt(0); //Пробел while(in.hasNext()){ c = (int)in.next().charAt(0); System.out.print((char)((c*a+b)%256)); System.out.print((char)((c*a+b)/256)); } } } |
Условие задачи MS15.
Найдите способ и напишите программу расшифровки текста зашифрованного в предыдущем задании по известным [latex]a[/latex] и [latex]b[/latex].
Входные данные:
Два ключа через пробел и, через ещё один пробел, зашифрованный текст.
Выходные данные:
Расшифрованный текст.
Тесты.
№ |
Входные данные |
Выходные данные |
|
[latex]a[/latex] |
[latex]b[/latex] |
Зашифрованный текст |
Расшифрованный текст |
1 |
f |
n |
P▲D*ж.ж.м(B,@. |
Kittens |
2 |
4 |
j |
◙☼ю¶z▬z▬ў▬z○ъ♠ц↑ў▬т↨z▬║¶▲• |
Hello, world! |
3 |
? |
. |
■♂=♀|♀╗♀·♀9♪x♪╖♪ў♪5♫ |
0123456789 |
Код на C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
#include <iostream> #include <cmath> using namespace std; int main() { unsigned char a, b, tmp, c1, c2; scanf("%c", &a); //Первый ключ scanf("%c", &c1); //Пробел scanf("%c", &b); //Второй ключ scanf("%c", &c1); //Пробел while (EOF != scanf("%c", &c1)) //Пока не кончатся входные данные { scanf("%c", &c2); tmp=round((c1-b+256*c2)*1.0/a); printf("%c", tmp); } return 0; } |
Код на Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
import java.util.*; import java.math.*; class Main { public static void main (String[] args) { Scanner in = new Scanner(System.in); in.useDelimiter(""); //Чтение по одному символу. //String a = new String(); int a = (int)in.next().charAt(0); //Первый ключ int c1 = (int)in.next().charAt(0); //Пробел int b = (int)in.next().charAt(0); //Второй ключ int c2 = (int)in.next().charAt(0); //Пробел while(in.hasNext()){ c1 = (int)in.next().charAt(0); c2 = (int)in.next().charAt(0); System.out.print((char) Math.round((c1-b+256*c2)*1.0/a)); } } } |
Решение.
Основной трудностью при решении задачи является тот момент, что при шифровке символов строго по формуле, указанной в условии MS14, а именно [latex]c=at+b \mod 256[/latex], символы зашифрованного текста могут расшифровываться неоднозначно. К примеру, при [latex]a=8[/latex] и [latex]b=1[/latex] после зашифровки символов [latex]@[/latex] и [latex]`[/latex] в обоих случаях получим символ с кодом [latex]1[/latex]. Это часто лишает расшифрованный текст какого-либо смысла. Так происходит, поскольку в переменных типа [latex]unsigned[/latex] [latex]char[/latex] могут храниться элементы с кодом от [latex]0[/latex] до [latex]255[/latex], и при попытке присвоить переменной большее значение совершается своеобразный «круг». Так, если ей присвоить значение [latex]257[/latex], при выводе получим символ с кодом [latex]1[/latex]. Сначала в ходе работы обеих программ вводятся два ключа, а лишние пробелы читаются в одну из переменных для хранения символов. Программа для зашифровки принимает символ, зашифровывает его по указанной формуле, и выводит, а сразу за ним — элемент с кодом, который высчитывается по другой формуле: [latex]c=(at+b) / 256[/latex]. Этот код совпадает с числом совершённых «кругов». Программа для расшифровки же на каждом цикле принимает эти два символа, и выводит символ исходного текста, код которого вычисляется округлением до целых значения выражения [latex]\frac { c1-b+256\cdot c2 }{ a } [/latex], где [latex]c1[/latex] — первый символ, а [latex]c2[/latex] — второй.
Условия задач.
Код MS14 на ideone.com(C++)
Код MS15 на ideone.com(C++)
Код MS14 на ideone.com(Java)
Код MS15 на ideone.com(Java)
Related Images:
Для отправки комментария необходимо войти на сайт.