Cod sursa(job #502103)

Utilizator vladbutnaruButnaru Vlad vladbutnaru Data 17 noiembrie 2010 19:13:09
Problema Cifra Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.55 kb
#include <iostream>
#include <algorithm>
#include <fstream>
#include <string>

using namespace std;

#define FILE_IN "cifra.in"
#define FILE_OUT "cifra.out"

/*
 * Insight: In mod evident, (N^N) % 10 = ((N%10)^N) % 10.
 * In timpul constructiei tabelei de a^b cu a,b=0..10 se constata
 * si ca (N^K) % 10 = (N^(K+4)) % 10 pentru K>0. De aici rezulta ca:
 *
 * (N^N) % 10 = ((N+40)^(N+40)) % 10
 *
 * deci sirul 1^1+2^2+... e periodic; se calculeaza suma unei perioade
 * ca fiind 8, deci calculul sumei se face din (N/40)*suma perioada + suma
 * manuala pentru restul termenilor.
 */

int POW[10][11];

int T;
char N[200];

void initPow()
{
	for (int i=0; i<10; i++)
	{
		POW[i][0] = i ? 1 : 0;
		for (int j=1; j<=10; j++) POW[i][j] = (POW[i][j-1]*i)%10;
	}
}

int nLaN(int n)
{
	int pw = n%4;

	return POW[n%10][pw ? pw : 4];
}

int div40(char* n)
{
	// imparte cu 4
	int rest = 0;
	char* ptr = n;
	while (*ptr)
	{
		rest = rest*10 + (*ptr-48);
		*ptr = 48 + (rest/4);
		rest = rest % 4;
		ptr++;
	}

	// imparte cu 10
	rest = (*(--ptr)-48)*4 + rest;
	*ptr = 0;
	if (ptr == n) *ptr = '0';

	return rest;
}

int main()
{
	initPow();

	ifstream fisIn(FILE_IN);
    ofstream fisOut(FILE_OUT);

    fisIn >> T;
    fisIn.getline(N, 2); // treci la lina urmatoare

    for (int i=0; i<T; i++)
    {
		fisIn.getline(N, 200);

		int rest = div40(N);
		int suma = (8*(N[strlen(N)-1]-48)) % 10; // suma perioadelor
		for (int j=1; j<=rest; j++) suma = (suma + nLaN(j)) % 10;

		fisOut << suma << "\n";
	}
}