• poj3358数论(欧拉定理)


    http://poj.org/problem?id=3358

    (初始状态为分数形式)小数点进制转换原理: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
    " , Case++ , ans1 , ans2 ) ;		
    	}
    	return 0 ;
    }
    


  • 相关阅读:
    ECMAScript 继承继承机制实现
    ECMAScript 函数定义类或对象
    药品查询APP开发流程(五)开发—yao_search.js
    ECMAScript 函数修改对象
    药品查询APP开发流程(六)开发—yao_category.js
    药品查询APP开发流程(四)开发—app.js
    药品查询APP开发流程(一)需求分析
    药品查询APP开发流程(三)开发—SQLite数据库
    ECMAScript 继承继承机制实例
    求最长递减子序列(转载)
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3217888.html
Copyright © 2020-2023  润新知