HDU3307A^B = C mod D,已知A,C,D,求解B

 
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''*g*m + 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;
}



你可能感兴趣的:(c,UP)