程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> poj3358數論(歐拉定理)

poj3358數論(歐拉定理)

編輯:C++入門知識

 

初始狀態為分數形式)小數點進制轉換原理:n / m ;

n /= gcd( n , m ) ;

m/= gcd( n , m ) ;

n = n % m ;

for( i : 0 to .....)

n *= k ;

bit[ i ] = n / m;(保留每一位的數值)

n %= m ;

題意:求n/m的小數點位的循環數列的長度和起始位置;

現在假設起始循環的第i個數為n,記作ni ;那麼第j個數n,則是nj;這時循環數列出現,那麼循環數列的長度為 L = j - i .

又根據小數點進制的計算原理,那麼就有nj = ( ni * 2 ^ L ) % m ;————>2 ^ L % m == 1 % m ;(求t是利用這裡求的)

 當 m  與 2 互質時,根據歐拉定理,則有2^ phi( m ) == 1 %m ,因為2^ 0 == 1 , 所以起始點為0 ;也就是題目的1;

當二者不互質時,那麼m % 2 != 0 ;

因此對等式進行化簡 ,兩邊同時除以2的冪次(使得m與2互質,直到滿足歐拉函數的條件),那麼就有2^( L - t ) == 1 % ( m / ( 2 ^ t );可知,此時循環數列的起點為 t ,也就是題目的t+1;

最後我們要求的就是2^ L' = 1 % M' ;由於2^ k == 1 % m ',當k % m == 0 時取得有效值,因此,從小到大枚舉phi(m')的因子,可得到最大值

 

#include<iostream>   
#include<cstdio>   
#include<cstring>   
#include<cmath>   
#include<algorithm>   
#include<bitset>   
#include<iomanip>   
  
using namespace std;  
int t, n, m, GCD, phi, ans1, ans2;  
int temp, num;  
int fac[1000000];  
   
int gcd( int a , int b )  
{  
    return b == 0 ? a : gcd( b , a % b );  
}  
  
int euler(int n)  
{  
    int ret=1,i;  
    for (i=2;i*i<=n;i++)  
        if (n%i==0)  
        {  
            n/=i,ret*=i-1;  
            while (n%i==0)  
                n/=i,ret*=i;  
        }  
    if (n>1)  
        ret*=n-1;  
    return ret;  
}  
int Pow( int a , int b , int c )  
{  
    int ans = 1 ;   
    while( b > 0 )  
    {  
        if( b & 1 )  
        {  
            ans = ( long long ) ans * a % c ;  
        }  
        b >>= 1 ;  
        a = ( long long )a * a % c ;  
    }  
    return ans ;  
}   
   
int main()  
{  
    int Case = 1 ;  
    while( scanf( "%d/%d" , &n , &m ) != EOF )  
    {  
        GCD = gcd( n , m ) ;  
        n /= GCD ;  
        m /= GCD ;  
        t = 0 ;  
        while( m % 2 == 0 )  
        {  
            t++ ;  
            m /= 2 ;  
        }  
        ans1 = t + 1 ;  
        phi = euler( m ) ;  
        if( phi == 1 )  
        {  
            ans2 = 1 ;   
        }  
        else  
        {  
            int num = 0 ;  
            for( int i = 1 ; i * i <= phi ; ++i )  
            {  
                if( phi % i == 0 )  
                {  
                    fac[ num++ ] = i ;  
                    fac[ num++ ] = phi / i ;  
                }  
            }  
            sort( fac , fac + num ) ;  
            for( int i = 0 ; i < num ; ++i )  
            {  
                temp = Pow( 2 , fac[ i ] , m ) ;  
                if( temp == 1 )  
                {  
                    ans2 = fac[ i ] ;   
                    break ;  
                }  
            }  
        }  
        printf( "Case #%d: %d,%d\n" , Case++ , ans1 , ans2 ) ;        
    }  
    return 0 ;  
}  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<iomanip>

using namespace std;
int t, n, m, GCD, phi, ans1, ans2;
int temp, num;
int fac[1000000];
 
int gcd( int a , int b )
{
	return b == 0 ? a : gcd( b , a % b );
}

int euler(int n)
{
	int ret=1,i;
	for (i=2;i*i<=n;i++)
		if (n%i==0)
		{
			n/=i,ret*=i-1;
			while (n%i==0)
				n/=i,ret*=i;
		}
	if (n>1)
		ret*=n-1;
	return ret;
}
int Pow( int a , int b , int c )
{
	int ans = 1 ; 
	while( b > 0 )
	{
		if( b & 1 )
		{
			ans = ( long long ) ans * a % c ;
		}
		b >>= 1 ;
		a = ( long long )a * a % c ;
	}
	return ans ;
} 
 
int main()
{
	int Case = 1 ;
	while( scanf( "%d/%d" , &n , &m ) != EOF )
	{
		GCD = gcd( n , m ) ;
		n /= GCD ;
		m /= GCD ;
		t = 0 ;
		while( m % 2 == 0 )
		{
			t++ ;
			m /= 2 ;
		}
		ans1 = t + 1 ;
		phi = euler( m ) ;
		if( phi == 1 )
		{
			ans2 = 1 ; 
		}
		else
		{
			int num = 0 ;
			for( int i = 1 ; i * i <= phi ; ++i )
			{
				if( phi % i == 0 )
				{
					fac[ num++ ] = i ;
					fac[ num++ ] = phi / i ;
				}
			}
			sort( fac , fac + num ) ;
			for( int i = 0 ; i < num ; ++i )
			{
				temp = Pow( 2 , fac[ i ] , m ) ;
				if( temp == 1 )
				{
					ans2 = fac[ i ] ; 
					break ;
				}
			}
		}
		printf( "Case #%d: %d,%d\n" , Case++ , ans1 , ans2 ) ;		
	}
	return 0 ;
}


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved