Cod sursa(job #509827)

Utilizator liviu12345Stoica Liviu liviu12345 Data 11 decembrie 2010 20:10:45
Problema Suma si numarul divizorilor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.41 kb
#include <cstdio>
#include <cstdlib>
#include <bitset>

using namespace std ;

const int MODULO = 9973 ;
const int PINV = 9971 ;

bitset <1000000> ciur ;

inline int ridicarePutere ( long long Baza , int Exponent )
{
  if ( Baza < 0 )
    Baza += MODULO ;
  if ( Baza == 0 )
    return MODULO ;
  Baza %= MODULO ;
  long long rezultat = 1 ; int  bit = 1 ;
  while ( Exponent )
  {
    if ( Exponent & bit )
    {
      rezultat *= Baza ;
      rezultat %= MODULO ;
    }
    Baza *= Baza ;
    Baza %= MODULO ;
    Exponent >>= 1 ;
  }
  if ( rezultat )
    return rezultat ;
  return MODULO ;
}

inline int sqrt ( long long X )
{
  int St = 1 , Dr = X , mid ;
  while ( Dr - St > 1 )
  {
    mid = ( St + Dr ) >> 1 ;
    if ( mid * mid > X )
      Dr = mid ;
    else
      St = mid ;
  }
  return Dr ;
}

int main ( )
{
  freopen ( "ssnd.in" , "r" , stdin ) ;
  freopen ( "ssnd.out" , "w" , stdout ) ;
  int bit = 1 ;
  long long p2 , nrCurent;
  int nrOperatii ;
  int nrDivizori , sumaCurenta , p , Stop ;
  scanf ( "%d" , &nrOperatii ) ;
  for ( int i = 0 ; i < nrOperatii ; ++i )
  {
    scanf ( "%lld" , &nrCurent ) ;
    nrDivizori = 1 ;
    sumaCurenta = 1 ;
    Stop = sqrt ( nrCurent ) ;
    if ( ! (nrCurent & bit) )
    {
      p = 1 ;
      while ( !(nrCurent & bit) )
      {
	nrCurent >>= 1 ;
	++p ;
      }
      nrDivizori *= p ;
      p2 = 1 << p ;
      --p2 ;
      p2 %= MODULO ;
      sumaCurenta = p2 ;
    }
    for ( int j = 3 ; j <= Stop ; j += 2 )
    {
      if ( ciur [ j ] ) continue ;
      p = 1 ;
      while ( nrCurent % j == 0 )
      {
	nrCurent /= j ;
	++p;
      }
      if ( p > 1 )
      {
	nrDivizori *= p ;
	sumaCurenta *= ( ( ridicarePutere ( j , p ) - 1 ) * ridicarePutere ( ( j - 1 ) , PINV ) ) % MODULO ;
	sumaCurenta %= MODULO ;
	Stop = sqrt ( nrCurent ) ;
      }
    }
    if ( nrCurent == 1 )
    {
      printf ( "%d %d\n" , nrDivizori , sumaCurenta ) ;
    }
    else
    {
      nrDivizori <<= 1 ;
      p = nrCurent  % MODULO;
      sumaCurenta *= ( ( ridicarePutere ( p , 2 ) - 1 ) * ridicarePutere ( ( p - 1 ) , PINV ) ) % MODULO ;
      sumaCurenta %= MODULO ;
      printf ( "%d %d\n" , nrDivizori , sumaCurenta ) ;
    }
  }
}

void generareCiur ( )
{
  int p , j ;
  for ( int i = 2 ; i < 1000000 ; i += 2 )
    ciur [ i ] = true ;
  for ( int i = 3 ; i < 1000 ; i += 2 )
  {
    if ( ciur [ i ] ) continue ;
    p = i << 1 ;
    for ( j = i * i ; j < 1000000 ; j += p )
      ciur [ i ] = true ;
  }
}