#include <graphics.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream.h>
#include <time.h>

	  enum Boolean{ false,true};

	// базовый класс
	class Location { //Абсолютные координаты
	  //	protected:
		public:
		int X;
		int Y;

		public:
		Location(int InitX,int InitY){X=InitX;Y=InitY;}
		int GetX();
		int GetY();
		};
//Точка
	class Point:public Location{
		protected:
		Boolean Visible;
		int color;

		public:
		Point (int InitX,int InitY,int Scolor);
		virtual void Show();
		virtual void Hide();
		Boolean IsVisible() {return Visible;}
	 //	setcolor (int color);
		};
//окружность
	class Circle : public Point{
		int b;
		protected:
		int Radius;

		public:
		Circle (int InitX,int InitY,int Initradius,int Scolor,int b=0);
		void Show();
		void Show1();
		void Hide();
	     //	void CopyTO(int NewX,int NewY);
		};
//строка
	class Str:public Point{
		protected:
		int size;
		int Font;
		char *msg;
		char lk[12];



		public:
		Str(int InitX,int InitY,char *text,int Ifont,
						       int Chsize,int Scolor);
		void Show();
		void Show1();
		void Show2();
		void Show3();
		void Show4();

		void Hide();
	     //	void CopyTO(int NewX,int NewY);
		};
//Линия
	class Line:public Point{
		protected:
		int endX,endY;

		public:
		Line(int InitX,int InitY,int IendX,int IendY,int Scolor);
		void Show();
		void Hide();
	      //void CopyTO();
	      };

//Прямоугольник
	class Rect:public Line {
		void far *bm;

		protected:
		int save;

		public:
		Rect (int InitX,int InitY,int IendX,int IendY,int Isave,
			int Scolor);
		void Show();
		void Hide();
	     //	void CopyTO(int NewX,int NewY,int NendX,int NendY);
		};

	class Mcircle:public Circle,Str{

		public:
		Mcircle(int MinitX,int MinitY,int Mradius,char *text,int Mfont,
			int Setcolor);
		void Show();
		};



//-----------------------------------------------------------------------
// Определение методов
// "точка"
	Point::Point(int InitX,int InitY,int Scolor): Location(InitX,InitY)
	{
	 color=Scolor;
	 Visible=false;
	};

	void Point::Show()
	{
	 Visible=true;
	 putpixel(X,Y,color);
	};

	void Point::Hide()
	{
	 Visible=false;
	 putpixel(X,Y,getbkcolor());
	};
//-----------------------------------------------------------------------
// "окружность"
	Circle::Circle (int InitX,int InitY,int Initradius,int Scolor,int Ib):
					    Point(InitX,InitY,Scolor)
	 {
	  Radius=Initradius;
	  b=Ib;
	 };

	void Circle::Show()
	{
	 Visible=true;
	 setcolor(color);
	 circle(X,Y,Radius);
	 if(b==0)
	   setcolor(getbkcolor());
	 for(int i=Radius-1;i>=0;--i)
	   circle(X,Y,i);
	};

	void Circle::Hide()
	{
	 setcolor(getbkcolor());
	 Visible = false;
	 circle(X,Y,Radius);
	};

	void Circle::Show1()
	{
	 Visible=true;
	 setcolor(color);
	 circle(X,Y,Radius);
	};


  /*	void CopyTO(int NewX,int NewY)
	{
	 X=NewX;
	 Y=NewY;
	 Show();
	};  */
//-----------------------------------------------------------------------
// "строка"
	 Str::Str(int InitX,int InitY,char *text,int Ifont,
		  int Chsize,int Scolor):Point(InitX,InitY,Scolor)
	  {
	   Font=Ifont;
	   size=Chsize;
	   msg=text;
	  };

	  void Str::Show1()
	  {
	   setcolor(color);
	   settextjustify(LEFT_TEXT,TOP_TEXT);
	   settextstyle(Font,HORIZ_DIR,size);
	   outtextxy(X,Y,msg);
	   };
	  void Str::Show()
	  {
	   int setsize=size/(strlen(msg))-1;
	   lk[1]=0;
	   lk[0]=*msg;

	   setcolor(15);
	   settextjustify(RIGHT_TEXT,CENTER_TEXT);
	   settextstyle(Font,HORIZ_DIR,setsize);
	   outtextxy(X,Y,lk);

	   lk[0]=* ++msg;
	   settextjustify(LEFT_TEXT,BOTTOM_TEXT);
	   settextstyle(Font,HORIZ_DIR,setsize);
	   outtextxy(X,Y,lk);


	  }
	    void Str::Show4()
	  {
	    lk[0]=*msg;
	    lk[1]=' ';
	    lk[2]=' ';
	    lk[3]=0;
	   setcolor(color);
	   settextjustify(RIGHT_TEXT,TOP_TEXT);
	   settextstyle(Font,HORIZ_DIR,size);
	   outtextxy(X,Y,lk);

	    lk[0]=* ++msg;
	    lk[1]=* ++msg;
	    lk[2]=* ++msg;
	    lk[3]=* ++msg;
	    lk[4]=0;

	   setcolor(color);
	   settextjustify(RIGHT_TEXT,CENTER_TEXT);
	   settextstyle(Font,HORIZ_DIR,size-1);
	   outtextxy(X,Y,lk);

	   settextjustify(LEFT_TEXT,TOP_TEXT);
	   settextstyle(Font,HORIZ_DIR,size);
	   outtextxy(X,Y,++msg);

	  }

	    void Str::Show2()
	  {
	   setcolor(color);
	   settextjustify(CENTER_TEXT,CENTER_TEXT);
	   settextstyle(Font,HORIZ_DIR,size);
	   outtextxy(X,Y,msg);
	  }
	    void Str::Show3()
	  {
	   setcolor(color);
	   settextjustify(2,CENTER_TEXT);
	   settextstyle(Font,HORIZ_DIR,size);
	   outtextxy(X,Y,msg);
	  }

	  void Str::Hide()
	  {
	   setcolor(getbkcolor());
	   settextjustify(LEFT_TEXT,TOP_TEXT);
	   settextstyle(Font,HORIZ_DIR,size);
	   outtextxy(X,Y,msg);
	    setcolor(color);
	  }


     /*	void CopyTO(int NewX,int NewY)
	{
	 X=NewX;
	 Y=NewY;
	 Show();
	};     */
//------------------------------------------------------------------------
// "линия"
	Line::Line(int InitX,int InitY,int IendX,int IendY,int Scolor):
			Point(InitX,InitY,Scolor)
	  {
	   endX=IendX;
	   endY=IendY;
	  };
	void Line::Show()
	{
	 setcolor(color);
	 line(X,Y,endX,endY);
	}
	void Line::Hide()
	{
	 setcolor(getbkcolor());
	 line(X,Y,endX,endY);
	};

//------------------------------------------------------------------------
// "описанная окружность"

       Mcircle::Mcircle(int MinitX,int MinitY,int Mradius,char *text,
			int Mfont,int Setcolor):Circle(MinitX,MinitY,Mradius,
			Setcolor),Str(MinitX,MinitY,text,Mfont,Mradius,Setcolor)
	{
	};

       void Mcircle::Show()
       {
	Circle::Show();
	Str::Show();
       };

//-----------------------------------------------------------------------
// "прямоугольник"
	Rect::Rect(int InitX,int InitY,int IendX,int IendY,int Scolor,
			int Isave):Line(InitX,InitY,IendX,IendY,Scolor)
	  {
	   save=Isave;
	  };
	  void Rect::Show()
	  {
	    if(save==1){
	       int z=imagesize(X,Y,endX,endY);
	       bm = malloc(z);
	       getimage(X,Y,endX,endY,bm);
	       setfillstyle(SOLID_FILL,color);
	       setcolor(color);
	       bar(X,Y,endX,endY);}

	     if(save==0){
	       setcolor(color);
	       rectangle(X,Y,endX,endY); }
	    if(save>1){
	       setfillstyle(SOLID_FILL,color);
	       setcolor(color);
	       bar(X,Y,endX,endY); }
	   };

	   void Rect::Hide()
	   {
	    if(save!=0){
	       putimage(X,Y,bm,0);
	       free(bm);}
	    else {
		setcolor(getbkcolor());
		rectangle(X,Y,endX,endY);
		}
	      }
 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	 void Graf(int,int,int,int,int),Gin(int,int,int,int,int,int),In_se1(int);
	 void Sort(int),Border(int,int,int,int,char *,char *,int),In_se(int);
	 void NN(int),Step0(int),Step1(int),Step2(int),Step3(int),Step4(int);
	 void StepZ(int),StepN(int),QW(int),SF(int),Chek(int,char *);
	 void PROGRM(int,int),PROGRM1(int,int),PROGRM2(int,int),HELP_PNL(int,int);
	 void Matrica(int,int,int,int,int),Nm(int,int,int),Excircle(int,int);
	 int MOD1(int,int),Fm(int),NM(int,int),FM(int,long) ;
	 long MOD(long,int);
	 int SQR(int), Cmp(int,int);
	 void OK_Show(void),Hello(void);
	 long Alfa[16],F[16],S[16],Ts[16];
	 int M[16][16][2];


	 char *Coob[]={
	 "ТЕОРЕТИКО-ЧИСЛОВЫЕ ПРЕОБРАЗОВАНИЯ",
	 "Модульная арифметика",
	 "Вычисление свертки ТЧП"
	 };
	 char *Help[]={
	 "ВЫПОЛНЕНИЕ   АВТОСВЕРТКИ",
	 "Исходная последовательность",
	 "Преобразование,умноженное на N' ",
	 "После изм-ния знака показателя степени",
	 "После двоичной инверсии",
	 "После первого этапа вычислений",
	 "После второго этапа вычислений",
	 "После третьего этапа вычислений",
	 "После четвертого этапа вычислений",
	 "После возведения в квадрат"
	 };
	 char *Help1[]={
	 "ПРЯМОЕ  ТЧП",
	 "ОБРАТНОЕ  ТЧП",
	 "M=17 р=4 N=4",
	 "M=17 р=8 N=8",
	 " M=65537 р=4 N=16"};

	 char *Help2[]={
	 "Вычислить автосвертку последовательности",
	 "Введите значения для строк матрицы прямого преобразования",
	 "Введите значения для строк матрицы обратного преобразования",
	 "Результат прямого пребразования A=T * S",
	 "Результат обратного пребразования A=N'(T^-1) * S",
	 "T= ","-1 "};

	 char *Help3[]={
	 "ТЕОРЕМА ЭЙЛЕРА",
	 "af(M)Ё1modM",
	 "доказывает, что любое число а взаимнопростое с М позволяет сформировать",
	 " степенную  последовательность  а^n  для всех членов которой существуют ",
	 " мультипликативно обратные им числа по модулю  М , а  период полученной",
	 " степенной последовательности является делителем f(M)-количества взаимно-",
	 " простых и меньших чем М чисел",
	 "введите значение основания а взаимнопростое с М=17",
	 "a=",
	 "сформируйте числовой ряд по степеням основания",
	 "установите периодичность (порядок числа а по М)",
	 "и кратность функции f(M) к N",
	 "N=",
	 "f(M)/N=" };

	 char *Kf[]={"р0","р1","р2","р3","р4","р5","р6","р7"};
	 char *Sx[]={"(0)","(1)","(2)","(3)","(4)","(5)","(6)","(7)",
		 "(8)","(9)","(10)","(11)","(12)","(13)","(14)","(15)"};

	 char *Fx[70];
	 char *s, *q, *r;

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



       main()
       {
	 s=(char *)malloc(100);
	 r=(char *)malloc(100);
	 q=s;
	int graphdrive = DETECT,graphmode;
	initgraph(&graphdrive,&graphmode," ");


	Border(1,20,639,478,Coob[0],Coob[1],10);
	//Fx=(char *) malloc(16*6);
	setviewport(2,42,637,455,1);
	Hello();
	PROGRM2(16,0);
	setviewport(0,0,639,479,0);
	clearviewport();


	Border(1,20,639,478,Coob[0],Coob[2],10);
	setviewport(2,42,637,455,1);

	In_se(4);
	PROGRM1(4,0);
	clearviewport();
	PROGRM1(4,1);
	clearviewport();
	In_se(4);
	PROGRM(4,0);
	clearviewport();
	PROGRM(4,1);
	clearviewport();

	In_se(8);
	PROGRM1(8,0);
	clearviewport();
	PROGRM1(8,1);
	clearviewport();
	In_se(8);
	PROGRM(8,0);
	clearviewport();
	PROGRM(8,1);
	clearviewport();

	In_se(16);
	PROGRM1(16,0);
	clearviewport();
	PROGRM1(16,1);

	clearviewport();
	In_se(16);
	PROGRM(16,0);
	clearviewport();
	PROGRM(16,1);
	OK_Show();
	getch();
	closegraph();
	}



	void PROGRM2(int typ,int forword)
	{  int i,k;
	Str KD40(320,20,Help3[0],DEFAULT_FONT,3,4);
	Str KD41(280,40,Help3[1],TRIPLEX_FONT,4,10);
	Str KD42(320,90,Help3[2],DEFAULT_FONT,0,15);
	Str KD43(320,100,Help3[3],DEFAULT_FONT,0,15);
	Str KD44(320,110,Help3[4],DEFAULT_FONT,0,15);
	Str KD45(320,120,Help3[5],DEFAULT_FONT,0,15);
	Str KD46(320,130,Help3[6],DEFAULT_FONT,0,15);

	Rect KD54(220,30,420,75,15,0);
	Rect KD55(30,80,610,140,15,0);
	 KD40.Show2();
	 KD41.Show4();
	 KD42.Show2();
	 KD43.Show2();
	 KD44.Show2();
	 KD45.Show2();
	 KD46.Show2();
	 KD54.Show();
	 KD55.Show();

	 for(i=0,k=150;i<3;i++){
	  Str KD47(320,k,Help3[7],DEFAULT_FONT,0,9);
	  Str KD48(280,k+=7,Help3[8],SMALL_FONT,5,10);

	  KD47.Show2();
	  KD48.Show2();
	   S[0]= Fm(17);
	   Gin(293,k-4,4,3,0,4);

	Str KD49(320,k+=13,Help3[9],DEFAULT_FONT,0,9);
	  KD49.Show2();
	   S[1]=NM(Ts[0],17);
	  Gin(180,k+2,S[1],4,0,35);

	Str KD50(320,k+=25,Help3[10],DEFAULT_FONT,0,9);
	Str KD51(320,k+=10,Help3[11],DEFAULT_FONT,0,9);
	Str KD52(250,k+=10,Help3[12],SMALL_FONT,5,10);

	 KD50.Show2();
	 KD51.Show2();
	 KD52.Show2();
	  S[3]=S[1];
	  Gin(265,k-5,1,2,0,4);
	Str KD53(360,k,Help3[13],SMALL_FONT,5,10);

	 KD53.Show2();
	  S[3]=S[0]/S[1];
	  Gin(385,k-5,1,2,0,4);
	  k+=15;
	 }
       }







	void PROGRM1(int typ,int forword)
	{  int i,k;
	Str KD20(320,20,Help2[0],DEFAULT_FONT,0,3);
	Str KD21(320,40,s,DEFAULT_FONT,0,15);
	Str KD22(320,60,Help1[0],DEFAULT_FONT,2,9);
	Str KD23(320,60,Help1[1],DEFAULT_FONT,2,9);
	Str KD24(320,80,Help1[2],TRIPLEX_FONT,0,10);
	Str KD25(320,80,Help1[3],TRIPLEX_FONT,0,10);
	Str KD26(320,80,Help1[4],TRIPLEX_FONT,0,10);
	Str KD27(320,105,Help2[1],DEFAULT_FONT,0,6);
	Str KD28(320,105,Help2[2],DEFAULT_FONT,0,6);
	Str KD29(320,370,Help2[3],DEFAULT_FONT,0,6);
	Str KD30(320,370,Help2[4],DEFAULT_FONT,0,6);
	 KD20.Show2();
	 KD21.Show2();
	if(typ==4){
	 KD24.Show2();
	 Matrica(220,175,typ,15,forword);}
	if(typ==8){
	 KD25.Show2();
	 Matrica(150,170,typ,15,forword);}
	if(typ==16){
	 KD26.Show2();
	 Matrica(60,150,typ,12,forword);}
	if(forword==0){
	  KD22.Show2();
	  KD27.Show2();
	 }
	else{
	 QW(typ);
	 StepN(typ);
	 SF(typ);
	  KD23.Show2();
	  KD28.Show2();}
	 for(i=0;i<typ;i++){
	  F[i]=0;
	  Nm(typ,i,forword);
	  for(k=0;k<typ;k++)
	   F[i] +=S[k] * Alfa[k];
	  F[i]=MOD(F[i],typ);
	  Gin(50,115,typ,1,i,70);
	 }
	 if(forword==0)
	  KD29.Show2();
	 else
	  KD30.Show2();
	  Gin(50,385,typ,0,0,70);
	 }

	void PROGRM(int typ,int forword)
       {
	int lw,f,b,k,l;
	NN(typ);
	lw=textheight("H");

	k=SQR(typ);

	if(typ==4){
	  Graf(20,150,4,45,19);
	  b=2;}
	 else
	  if(typ==8){
	    Graf(20,100,8,33,10);
	    b=3;}
	  else
	   if(typ==16){
	     Graf(20,25,16,25,10);
	     b=4;}


	  f=40;
	   Str KD2(455,f,Help[0],DEFAULT_FONT,1,9);
	    KD2.Show2();
	    f+=lw;

	   Str KD11(460,f,Help1[b],TRIPLEX_FONT,3,10);
	    KD11.Show2();
	    f+=lw*3;

	for(b=0,l=typ-1;b<typ;b++,l--){
	   Str KD15(M[b][k-1][0]+(60/k),M[b][k-1][1],Sx[l],SMALL_FONT,4,7);
	    KD15.Show1();}

	Sx[0]="(0)"; Sx[1]="(1)"; Sx[2]="(2)"; Sx[3]="(3)"; Sx[4]="(4)";
	      Sx[5]="(5)"; Sx[6]="(6)"; Sx[7]="(7)"; Sx[8]="(8)"; Sx[9]="(9)";
	      Sx[10]="(10)"; Sx[11]="(11)"; Sx[12]="(12)"; Sx[13]="(13)";
	      Sx[14]="(14)"; Sx[15]="(15)";



	 if(forword!=0){
	   Str KD12(455,f,Help1[1],DEFAULT_FONT,2,12);
	    KD12.Show2();
	    f+=lw;
	   Str KD(350,f,Help[2],DEFAULT_FONT,0,6);
	    KD.Show1();
	    StepN(typ); // Умножение на N'
	    Gin(350,f+lw,typ,0,0,35);
	   f+=(lw+2)*2;

	   Str KD1(350,f,Help[3],DEFAULT_FONT,0,6);
	    KD1.Show1();

	    StepZ(typ); // изменение знака показателя степени
	    Gin(350,f+lw,typ,0,0,35);
	    SF(typ);
	   f+=(lw+2)*2;}
	   else{

	   Str KD13(455,f,Help1[0],DEFAULT_FONT,2,12);
	    KD13.Show2();
	    f+=lw;

	   Str KD3(350,f,Help[1],DEFAULT_FONT,0,6);
	    KD3.Show1();
	    f+=lw;

	   Str KD10(350,f,s,DEFAULT_FONT,0,15);
	    KD10.Show1();
	    f+=lw;
	   }

	   Str KD4(350,f,Help[4],DEFAULT_FONT,0,6);
	    KD4.Show1();
	   Step0(typ);               // двоичная инверсия
	    Gin(350,f+lw,typ,0,0,35);
	    f+=(lw+2)*2;
	   for(b=0;b<typ;b++){
	   Str KD14(M[b][0][0],M[b][0][1],Fx[b],SMALL_FONT,4,7);
	    KD14.Show3();}

	   Str KD5(350,f,Help[5],DEFAULT_FONT,0,6);
	    KD5.Show1();
	    Step1(typ);             // перый этап
	    Gin(350,f+lw,typ,0,0,35);
	    f+=(lw+2)*2;
	    Excircle(typ,1);

	   Str KD6(350,f,Help[6],DEFAULT_FONT,0,6);
	    KD6.Show1();
	    Step2(typ);             // второй этап
	    Gin(350,f+lw,typ,0,0,35);
	    f+=(lw+2)*2;
	   Excircle(typ,2);

	 if(typ==8 || typ==16){
	   Str KD7(350,f,Help[7],DEFAULT_FONT,0,6);
	    KD7.Show1();
	    Step3(typ);    // третий этап
	    Gin(350,f+lw,typ,0,0,35);
	    f+=(lw+2)*2;
	   Excircle(typ,3);}

	 if(typ==16){
	   Str KD8(350,f,Help[8],DEFAULT_FONT,0,6);
	    KD8.Show1();
	    Step4(typ);           // четвертый этап
	    Gin(350,f+lw,typ,0,0,35);
	    f+=(lw+2)*2;
	    Excircle(typ,4);}

	  if(forword==0){
	  Str KD9(350,f,Help[9],DEFAULT_FONT,0,6);
	  KD9.Show1();
	  QW(typ);
	  Gin(350,f+lw,typ,0,0,35);
	  f+=(lw+2)*2; }
	 }

	 void Matrica(int X,int Y,int typ,int size,int flag)
	 {
	 struct linesettingstype ll;
	  int i,k;
	  for(i=0;i<typ;i++){
	   for(k=0;k<typ;k++){
	    M[k][i][0]=X+(k*size*3);
	    M[k][i][1]=Y+(i*size);
	    Point K(M[k][i][0],M[k][i][1],7);
	    K.Show(); }
	    }
	    Line ON(M[0][0][0]-typ-3,M[0][0][1]-10,
		    M[0][typ-1][0]-typ-3,M[0][typ-1][1]+10,4);
	    Line DO(M[typ-1][0][0]+(typ*2),M[typ-1][0][1]-10,
		M[typ-1][typ-1][0]+(typ*2),M[typ-1][typ-1][1]+10,4);

	    Str KD31(M[0][0][0]-typ+5,(M[0][typ-1][1]+M[0][0][1])/2,Help2[5],
							DEFAULT_FONT,2,4);
	    Str KD32(M[0][0][0]-(typ+10),((M[0][typ-1][1]+M[0][0][1])/2)-12,
						 Help2[6],DEFAULT_FONT,1,4);
	      getlinesettings(&ll);
	      setlinestyle(0,0,3);
	      ON.Show();
	      DO.Show();
	    if(flag!=0)
	     KD32.Show3();
	     KD31.Show3();
	     setlinestyle(ll.linestyle,ll.upattern,ll.thickness);
	 }

	void Graf(int InitX,int InitY,int type,int Isize,int Iradius)
	{ int d,k,f,s,l,m,flag;

	  f=SQR(type);
	  for(d=0;d<type;d++){
	   for(k=0;k<f;k++){
	   M[d][k][0]=InitX+(k*Isize*3);
	   M[d][k][1]=InitY+(d*Isize);
	   }
	 }
	  for(k=0,m=1,flag=0; k<(f-1) ;k++,m*=2){
	  for(d=0,s=1; d<type ;d++,++s){
	   if(flag==0){
	    Line AA(M[d][k][0],M[d][k][1],M[d][k+1][0],M[d][k+1][1],4);
	    AA.Show();}
	   else{
	    Line AK(M[d][k][0],M[d][k][1],M[d][k+1][0],M[d][k+1][1],12);
	    AK.Show();}
	    if(s==m && flag==0){
	     flag=1;
	     s=0;}
	    else{
	     if(s==m && flag==1){
	     flag=0;
	     s=0;}
	       }
	     }
	   }
	  Sort(type);

	  for(d=0;d<type;d++){
	   for(k=0;k<(f-1);k++){
	    Line AA(M[d][k][0],M[d][k][1],M[d][k+1][0],M[d][k+1][1],4);
	  AA.Show();}
	  }

	   for(k=1,m=2; k<f ;k++,m*=2){
	    for(d=0,s=m-1,flag=0;d<type;d++,s--){
	     if(flag==0 && s<0){
	      flag=1;s=m-1;}
	     if(flag==1 && s<0){
	      flag=0;s=m-1;}
	     if(flag==0 && s>=0){
	      Circle AM(M[d][k][0],M[d][k][1],Iradius,3);
	       AM.Show();}
	      else{
	      Mcircle AB(M[d][k][0],M[d][k][1],Iradius,Kf[s*(type/(m*2))],SMALL_FONT,3);
	      AB.Show();}

	     }
	    }
	   };


	void Sort(int typ)
	{
	 int TimeX,TimeY;
	 int i,d,k,f,s,g,l,n,t;
	  k=2;
	  g=i=typ/k;
	  f=SQR(typ);
	  for(s=1 ;f>1; k=k*2,s++,f--,i=g){
	   for(d=0,n=l=k-1;i>0;d=n+1,n=l=d+(k-1)){
	    for(t=0;(l-d)>=1;d++,l--,i--,t++){

	    TimeX=M[d][s][0];
	    TimeY=M[d][s][1];
	    M[d][s][0]=M[l][s][0];
	    M[d][s][1]=M[l][s][1];
	    M[l][s][0]=TimeX;
	    M[l][s][1]=TimeY;
	    }
	   }
	  }
	 };


	  int SQR(int t)
	  {
	   int o,g;
	   for(o=0,g=t;g>1;o++)
	    g=g/2;
	   o++;
	   return(o);
	   }
	   void Border(int Ix,int Iy,int Iex,int Iey,char *msg1,char *msg2,
								int Color)
	   {
	     Rect KA(Ix,Iy,Iex,Iey,Color,0);
	     Str KB(Iex/2,Iy+15,msg1,DEFAULT_FONT,2,Color+1);
	     Str KC(Iex/2,Iey-15,msg2,DEFAULT_FONT,2,Color+3);
	     KA.Show();
	     KB.Show2();
	     KC.Show2();
	   };

	 void Step0(int typ) //двоичная инверсия S -> F
	 {
	  int k,d;

	  static int B0=1;
	  static int B1=2;
	  static int B2=4;
	  static int B3=8;

	unsigned int R0,R1,R2,R3;

	unsigned int BinP ;
	unsigned int BinInv;

		 d=SQR(typ);

		for(k=0,BinP=1;k<(typ-2);k++,BinP++){

		R0=BinP & B0;
		R1=BinP & B1;
		R2=BinP & B2;
		R3=BinP & B3;

		switch(d){

			case 3:	R0=R0 << 1;
				R1=R1 >> 1;
				break;

			case 4:	R0=R0 << 2;
				R2=R2 >> 2;
				break;

			case 5: R0=R0 << 3;
				R1=R1 << 1;
				R2=R2 >> 1;
				R3=R3 >> 3;
				break;
			default: break;
			}

		 BinInv=R0 | R1 | R2 | R3;
		 F[BinP]=S[BinInv];
		 Fx[BinP]=Sx[BinInv];
		 }
		 F[0]=S[0];
		 F[typ-1]=S[typ-1];
		 Fx[0]=Sx[0];
		 Fx[typ-1]=Sx[typ-1];
		 }


	  void Step1(int typ)
	  {
	   long TimeF;
	   int i;
	    for(i=0;i<typ/2;i++){


		TimeF=F[i * 2] + F[i*2+1];
		F[i*2+1]=F[i*2] - F[i*2+1];

		F[i*2]=TimeF;
		F[i*2]=MOD(F[i*2],typ);
		F[i*2+1]=MOD(F[i*2+1],typ);
	     }
	   }



	  void Step2(int typ)
	  {
	   long TimeF;
	   int k,s,i;
	    for(i=k=s=0;i<typ/2;i++,k++){
		if(i==1 || i==3 || i==5 || i==7)
		  F[i*2+1]= F[i*2+1] * Alfa[typ/4];

	      if(k==2){
		s+=k;
		k=0;}


		TimeF=F[i+s] + F[i+s+2];
		F[i+s+2]=F[i+s] - F[i+s+2];

		F[i+s]=TimeF;
		F[i+s]=MOD(F[i+s],typ);
		F[i+s+2]=MOD(F[i+s+2],typ);
	     }
	   }

	  void Step3(int typ)
	  {
	   long TimeF;
	   int k,s,i;
	    for(i=k=s=0;i<typ/2;i++,k++){

	      if(k==4){
		s+=k;
		k=0;}

		F[i+s+4]= F[i+s+4] * Alfa[k * typ/8];

		TimeF=F[i+s] + F[i+s+4];
		F[i+s+4]=F[i+s] - F[i+s+4];

		F[i+s]=TimeF;
		F[i+s]=MOD(F[i+s],typ);
		F[i+s+4]=MOD(F[i+s+4],typ);
	     }
	   }



	  void Step4(int typ)
	  {
	   long TimeF;
	   int i;
	    for(i=0;i<typ/2;i++){

		F[i+typ/2]=F[i+typ/2] * Alfa[i];

		TimeF=F[i] + F[i+typ/2];
		F[i+typ/2]=F[i] - F[i+typ/2];

		F[i]=TimeF;
		F[i]=MOD(F[i],typ);
		F[i+typ/2]=MOD(F[i+typ/2],typ);
	     }
	  }
	  long MOD(long beta,int typ)

	  { long m;


	   switch (typ) {

		case 4:  m=17;break;

		case 8:  m=17;break;

		case 16: m=65537;break;
		}
		for(  ;(beta < 0) || (beta >= m);  ){
		  if(beta >= m)
		    beta-=m;
		  if(beta < 0)
		    beta+=m;
		   }
		 return(beta);
	     }


	  void NN(int typ)
	  {
	   int i,k;
	   if(typ==8)
	    k=8;
	   else
	    k=4;
	   Alfa[0]=1;
	   Alfa[1]=k * 1;

	   for(i=1;i<typ;i++){
	    Alfa[i+1]=Alfa[i] * k;
	    Alfa[i+1]=MOD(Alfa[i+1],typ);
	    }
	   }

	   void Nm(int typ,int p,int flag)
	   { int m,i,l,k;

	     switch(typ) {
	      case 4:   ;
	      case 16:  m=4;break;
	      case 8:   m=8;break;
	      };
	     for(i=0;i<typ;i++){
	      if(flag != 0)
	       l=i * (typ-p);
	      else
	       l=i*p;
		while(l>=typ)
		 l -=typ;
		Alfa[i]=1;
	      for(k=0;k<l;k++)
	       Alfa[i] *=m;
	      Alfa[i]=MOD(Alfa[i],typ);
	      }
	    }

	   void QW(int typ)
	   { int i;
	      for(i=0;i<typ;i++){
	       F[i]=F[i] * F[i];
	       F[i]=MOD(F[i],typ);
	       }
	   }

	   void StepZ(int typ)
	   { int i,k;
	     long TimeF;
	     char *TimeS;
	     for(i=1,k=typ-1;i!=k;k--,i++){
	      TimeF=F[i];
	      F[i]=F[k];
	      F[k]=TimeF;
	      TimeS=Sx[i];
	      Sx[i]=Sx[k];
	      Sx[k]=TimeS;
	      }
	    }

	    void StepN(int typ)
	    {
	     int i; long N;
		switch(typ) {

		  case 4 : N=13;break;

		  case 8 : N=15;break;

		  case 16 : N=61441;break;
		  }
	      for(i=0;i<typ;i++){
	       F[i]=F[i] * N;
	       F[i]=MOD(F[i],typ);
	       }
	      }
	     void SF(int typ)
	     { int i;
	       for(i=0;i<typ;i++)
		S[i]=F[i];

	     }

      void Gin(int x,int y,int typ,int mark,int MInitY,int space)
	{
	  int l,flag=1;
	  char key;
	  char *string,*fs,*fk;
	  char *dd[]={
	  "_",
	  " "
	  };
	  string=(char *) malloc(100);
	  settextstyle(SMALL_FONT,HORIZ_DIR,5);
	  fk=fs=string;
	  *string=*dd[0];
	  * ++string=0;


	  do{
	   Str AV(x,y,fk,SMALL_FONT,5,14);
	   AV.Show1();

	  key=getch();
	  if(key!=0){
	  switch(key){

	   case 27 :  AV.Hide();
		      string=fk=fs;
		      * string=*dd[0];
		      * ++string=0;
		      break;


	    case 13 :  Chek(typ,fs);
		       if(0==Cmp(typ,mark)){
			flag=0;

			AV.Hide();
			* --string=0;
			AV.Show1();
			break;}

		      AV.Hide();
		      string=fk=fs;
		      * string=*dd[0];
		      * ++string=0;
		      break;
	     case 8 : if((fs+1) < string){

		       AV.Hide();
		       * (string-2)=*dd[0];
		       * --string=0;}
		       if(fk>fs)
			--fk;
			break;

	   default :   AV.Hide();
		    * --string=key;
		    * ++string=*dd[0];
		    * ++string=0;
		      if((string-fs)>space)
		       ++fk;
		       break;

		}
	   }
	   else{
	     key=getch();
	     if(key==31)   // скан код вызова подсказки
	      HELP_PNL(typ,mark);
		}
	     } while(flag!=0);

	      for(l=0;l<typ && mark==1;l++){

	       if(l==0){
		Str AW(x,y,fk,SMALL_FONT,5,14);
		AW.Hide();
		string=strtok(fs," ");

	}
	     else  string=strtok(NULL," ");
	     Str KD33(M[l][MInitY][0],M[l][MInitY][1],string,
				SMALL_FONT,(9-SQR(typ)),15);
	      KD33.Show2();
	     }
	   }



	     int Cmp(int typ,int p)
	     {
	      int i,k,t;
	      long m;
	       if(typ==16)
		m=65537;
	       else
		m=17;
	      for(i=k=0;i<typ && k==0;i++)
	       { switch(p){

		case 0 :  if((F[i] != Ts[i]) && (Ts[i] != F[i]-m))
			    k=1;
			    break;
		case 1 :  if((Alfa[i] != Ts[i]) && (Ts[i] != Alfa[i]-m))
			    k=1;
			    break;
		case 2 :  if(S[3] != Ts[0])
			    k=1;
			    break;
		case 3 :  k=FM(17,Ts[0]);
			  if(k==0)
			    t=1;
			  else
			   { t=0;k=1;}
			    break;
		case 4 :  if((Alfa[i] != Ts[i]) && (Ts[i] != Alfa[i]-m))
			    k=1;
			    break;


		default :  k=1;break;
		  }
		}
		if(p==3)
		 return(t);
		else
		 return(k);
	      }

	     void Chek(int typ,char *Istr)
		{ int i;
		  char *ptr,*endptr;

		 for(i=0,ptr=endptr;i<typ && ptr==endptr;i++){
		  ptr=strchr(Istr,' ');
		  Ts[i]=strtol(Istr,&endptr,10);
		  Istr=endptr+1;
		 }
	       }


	    void In_se1(int typ)
	   { int i;
	     *s=0;
	     char *lock;
	      lock=(char *)malloc(10);


	    S[0]=1;S[1]=2;S[2]=0;S[3]=0;S[4]=3;S[5]=2;S[6]=4;S[7]=1;
	    S[8]=4;S[9]=2;S[10]=0;S[11]=1;S[12]=0;S[13]=4;S[14]=5;S[15]=4;
	     for(i=0;i<typ;i++){
	      strcat(s,ltoa(S[i],lock,10));
	      strcat(s," ");
	      }
	   }

	    void In_se(int typ)
	   { int i;
	     time_t t;
	     char *lock,*c;
	      lock=(char *)malloc(10);
	      c=s;
	      *c=0;
	      srand((unsigned) time(&t));
	     for(i=0;i<typ;i++){
	      S[i]=rand();
	      S[i]=MOD1(S[i],10);
	      strcat(s,ltoa(S[i],lock,10));
	      strcat(s," ");
	    //  free(lock);
	      }
	   }

	  void HELP_PNL(int typ,int mark)
	  {
	   char *lock,* c;
	   int i;
	   if(mark<2){
	   lock=(char *)malloc(10);
	   c=r;
	   *c=0;

	   Rect KK(10,230,628,250,1,1);
	   Str KP(320,240,c,SMALL_FONT,4,15);
	   for(i=0;i<typ;i++){
	    if(mark==0)
	     strcat(c,ltoa(F[i],lock,10));
	    else
	     strcat(c,ltoa(Alfa[i],lock,10));
	     strcat(c," ");
	   }
	   KK.Show();
	   KP.Show2();
	   getch();
	   KK.Hide();
	  free(lock);
	  }
	 }

	void OK_Show(void)
	{
	  int i;
	 char *c[]={
	 "*** ПОЗДРАВЛЯЕМ ***",
	 "с успешным завершением",
	 "лабораторной работы"
	 };
	 Rect Kk(100,100,540,280,1,2);
	 Kk.Show();
	 for(i=0;i<3;i++){
	  Str Kp(320,140+(i*20),c[i],DEFAULT_FONT,2,15);
	  Kp.Show2();}
	}

	void Hello(void)
	{

	  int i;
	 char *c[]={
	 "*** БЕЛАРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ***",
	 "**** ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ ****",
	 "лабораторная работа по",
	 "теоретико-числовым преобразованиям",
	 "рук.                 Митюхин А.И.",
	 "дипл.                Бернацкий Ю.Д",
	 "г.Минск                  1994г.",
	 };

	 Rect Ky(100,100,540,280,4,1);
	 Ky.Show();
	 for(i=0;i<7;i++){
	  Str Ku(320,140+(i*20),c[i],DEFAULT_FONT,1,15);
	  Ku.Show2();}
	  getch();
	  Ky.Hide();
	}


	 int Fm(int M)
	 {
	  int k,i,m,d=0,n=0;
	   for(k=0,i=2; k<(M-1); k++,i++){
	    for(m=M; m>0; )
	     m-=i;
	     if(m !=0 && k==0)
	     n=1;
	     if(m==0){
	     d+=1; F[k]=i;}
	     }
	     m=M-1;
	   return(m-d+n);
	 }


	 int FM(int M,long d)
	 { int m=0;

	    if((d>0) && (d< M)){
	    m=M;
	    for( ; m>0 ; )
	      m-=d;
	     if(m!=0)
	      m=1;}
	    return(m);
	  }



	int NM(int a,int mod)
	{
	 int i;

	   Alfa[0]=1;
	   Alfa[1]=a;

	   for(i=1;Alfa[i] !=1 ;i++){
	    Alfa[i+1]=Alfa[i] * a;
	    Alfa[i+1]=MOD1(Alfa[i+1],mod);
	    }
	    return(i);
	   }


	 int MOD1(int beta,int mod)
	 {
	  for( ;(beta<0) || (beta>=mod); ){
	   if(beta >= mod)
	    beta-=mod;
	   if(beta < 0)
	    beta+=mod;
	    }
	    return(beta);
	  }

	void Excircle(int typ,int step)
	{
	 int i,l;
	 if(typ==4)
	  l=19;
	 else
	  l=10;
	  for(i=0; i<typ; i++){
	   Circle C1(M[i][step][0],M[i][step][1],l,11);
	   C1.Show1();
	   }
	 }