ai = x ai-1 + y 递推容易得到 x^n -1 = m a0/t a0' = a0 / gcd(a0,t) 即 : x^n = 1 mod (a0') 在gcd (x,a0') != 1 时候无解 化简下来就是一个A^B = C mod D的形式,已知A,C,D,求解B。 其实很显然这是一个离散对数问题,这题比较特殊的是化简之后C = 1,也很容易的想到欧拉定理a ^ f(n) = 1 mod n, 题解就是枚举f(n)的各个因子,求出最小的 证明: x = g x' a0' = g a0'' g^n x^n = a0''gm + 1 g ( g^(n-1) x^n -m*a0'' ) = 1 在g > 1 时候 无解。 然后就容易了。求一下欧拉函数,枚举约数即可。

#include <iostream>
#include <cmath>
#include <string>
using namespace std;
#define FOR(i,s,e) for (int (i)=(s); (i)<(e); i++)
/*求素数[1,MAXPRI]*/
const int MAXPRI=50000+10;
bool NotPrime[MAXPRI];
int  PrimeList[MAXPRI];
void Prime()
{
    int i,j,up = sqrt(MAXPRI*1.0);
    memset(NotPrime,0,sizeof(NotPrime));
    memset(PrimeList,0,sizeof(PrimeList));
    for(i = 2; i <= up; i++) 
    {
        if(NotPrime[i] == 0)
        {
            PrimeList[++PrimeList[0]] = i;
            for(j = i + i; j < MAXPRI*1.0; j = j + i)
                NotPrime[j] = 1;
        }
    }
    for(i = up + 1; i < MAXPRI; i++)
        if(NotPrime[i] == 0)
            PrimeList[++PrimeList[0]] = i;
}
__int64  euler(__int64  x)
{
    int i ;
    __int64  res = x,up = (__int64 )sqrt(x * 1.0) + 1;
    for (i = 1; PrimeList[i] < up && i < PrimeList[0]; i++)
    if (x % PrimeList[i] == 0)
    {
        res = res / PrimeList[i] *( PrimeList[i] - 1);
        while (x % PrimeList[i] == 0 )
            x/=PrimeList[i];
     }
    if (x > 1)
        res = res / x * (x-1);
    return res;
}

__int64 gcd(__int64 a, __int64 b)
{
    if (a < b)
        return gcd(b,a);
    __int64 c ;
    while (b) 
    {
        c=a%b;
        a=b;
        b=c;
    }
    return a;
}
__int64  power_mod(__int64 A, __int64  B, __int64 C)
{
    __int64  R = 1, D = A;
    while (B )
    {
        if (B&1) R = (R*D)%C;
        D = (D*D)%C;
        B >>=1;
    }
    return R;
}

int main()
{
    __int64 x,y,a0,t;
    __int64 min,ph;
    Prime();
    while (scanf("%I64d%I64d%I64d",&x,&y,&a0)!=EOF)
    {
        t = y / (x-1);
        if (t % a0 == 0)  
        {
            printf("1\n");
            continue;
        }
        __int64 temp = gcd(a0,t);
        a0 = a0 / temp;
        if  (gcd(x,a0) != 1)
        {
            printf("Impossible!\n");
            continue;
        }
        /*A^B = C MOD D,其中A=X,C=1,D=a0, 求B*/
        ph = euler(a0);
        min = ph;
        for (int i=1; i*i<=ph; i++)
        if (ph % i == 0)
        {
            if (i<min && power_mod(x,i,a0) == 1)
                min = i;
            if (ph/i < min && power_mod(x,ph/i,a0) == 1)
                min = ph/i;
        }
        printf("%I64d\n",min);

    }
    return 0;
}

results matching ""

    No results matching ""