hdu 3307 欧拉定理+等比数列

利用等比数列知识,

an = x*an-1 + Y

故an +A = x * an-1 + Y + A

故an +A = x ( an-1 + (Y+A)/x)

令 A = (Y+A)/X

所以(X-1)*A = Y

得出 A = Y/(X-1)

所以{an+A}是等比数列;

所以an/a0 = X^n + P*(X^n-1)/a0

转换成X^n%(a0/p) = 1 符合欧拉定理,

所以由x^n组成的集合是个循环群,phi(a/p)是循环节,而且最小循环节必定是phi(a/p)的因数.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long LL;

LL euler ( LL x )
{
    LL res = x;
    for ( LL i = 2 ; i * i <= x ; i++ )
    {
        if ( x%i==0 )
           res -= res/i;
        while ( x%i==0 ) x/=i; 
    }
    if ( x > 1 ) res -= res/x;
    return res;
}

LL gcd ( LL x , LL y )
{
    return y==0? x : gcd ( y , x%y );
}

LL pow2 ( LL num ,LL index , LL mod  )
{
    if ( index == 0 ) return 1;
    LL temp = pow2 ( num , index/2, mod  );
    if ( index &1 ) return temp%mod*temp%mod*num%mod;
    else return temp%mod*temp%mod;
}

int main ( )
{
    LL x , y , a;
    while ( ~scanf ( "%lld%lld%lld" , &x , &y , &a ) )
    {
        if ( y == 0 ) 
        {
            puts("1");
            continue;
        }
        LL p = y/(x-1);
        a = a/gcd ( p , a );
        if ( gcd ( x , a) == 1 )
        {
            LL n = euler ( a );
            LL minn = n;
            for ( LL i = 2 ; i*i <= n ; i++ )
            {
                if ( n%i ) continue;
                if ( pow2 ( x , i ,a ) == 1 )
                    minn = min ( i , minn );
                if ( pow2 ( x , n/i , a ) == 1 )
                   minn = min ( n/i , minn ); 
            }
            printf ( "%I64d\n" , minn );
        }
        else puts ( "Impossible!" );
    }
}



你可能感兴趣的:(数论,最大公约数,欧拉定理)