欧拉定理:a^x 1(mod m),那么 x = euler(m);
题意:输入一个n,求能够整除n只由8组成的数的最小的位数;
思路:题目等价于满足(10^x - 1)/ 9 * 8 == n * p,其中p为整数,的x的最小值,n的范围2 * 10 ^ 9;
刚开始的时候,想直接把1,11,111,1111,……打一个表打到2*10^9,之后对输入的n进行除2,觉得除完除完之后就剩下了1,11,111,之类的数;然后再判断符合数组的哪个数,输出这个数的位数;然而,对于一个样例,就把这个想法推翻了,如输入3 的时候,输出的是3,因为888%3 == 0,所以不能采用这种方法,还是得重新推;
推导分析:
(10^x - 1)/ 9 * 8 == n * p ; 则10^x - 1 == n * p / 8 * 9; l令m == 9*n / gcd(n,8);
那么(10^x - 1)== m * p' ; 可以得到10 ^ x 1 (mod m);
可以知道,当m 和 10不互质的时候,肯定不符合答案;
然后x == euler(m),然后答案就是满足这个方程的是euler(m)的因数的最小的值;
在找满足方程的euler(m)的最小因数的时候为了防止超时,可以从访问到一半的位置,之后再进行除法进而判断后面的数的情况;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 40000 + 10;
bool is_prime[maxn];
int len;
ll prime[maxn];
//void Init()
//{
// len = 0;
// memset(is_prime,true,sizeof(is_prime));
// is_prime[0] = is_prime[1] = false;
// for(int i = 2; i < maxn ; i ++)
// {
// if(is_prime[i])
// for(int j = 2 * i ; j < maxn ; j += i)
// is_prime[j] = false;
// }
// prime[len ++] = 1;
// for(int i = 2; i < maxn ; i ++)
// {
// if(is_prime[i])
// prime[len ++] = i;
// }
//}
ll gcd(ll x,ll y)
{
return y == 0 ? x : gcd(y,x%y);
}
ll euler(ll x)
{
ll ans = x;
for(ll i = 2; i * i <= x; i ++)
{
if(x % i == 0)
{
ans = ans / i * (i - 1);
while(x % i == 0)
x = x/ i;
}
}
if(x > 1)
ans = ans / x * (x - 1);
return ans;
}
ll Mul(ll x,ll y,ll mod_val)
{
ll ans = 0;
while(y)
{
if(y & 1)
{
ans = (ans + x) % mod_val;
}
x = x * 2 % mod_val;
y >>= 1;
}
return ans;
}
ll pow_mod(ll x,ll n,ll mod_val)
{
ll ans = 1;
ll t = x%mod_val;
while(n)
{
if(n & 1)
{
ans = Mul(ans,t,mod_val);
}
t = Mul(t,t,mod_val);
n >>= 1;
}
return ans ;
}
int main()
{
// Init();
ll n;
int Tcase = 1;
while( ~ scanf("%I64d",&n) && n )
{
cout << "Case "<< Tcase ++ << ": ";
ll m =n / gcd(n,8) * 9;
if( gcd(10,m) != 1 )
{
cout << 0 << endl;
continue;
}
ll ans = euler(m);
ll anss = 10e18;
for(ll i = 1; i * i <= ans ; i ++)
{
if(ans % i == 0)
{
if(pow_mod(10,i,m) == 1)
anss = min(anss,i);
if(pow_mod(10,ans/i,m) == 1)
anss = min(anss,ans/i);
}
}
cout << anss << endl;
}
return 0;
}
分析:裸的欧拉定理:当gcd(n,x) > 1 或者 n ==1 的时候,不符合;否则 x = euler(n)的满足这个的最小因数;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100000 + 10;
//ll gcd(ll x,ll y)
//{
// return y == 0 ? x : gcd(y,x%y);
//}
ll euler(ll x)
{
ll ans = x;
for(ll i = 2; i * i <= x; i ++)
{
if(x % i == 0)
{
ans = ans / i * (i - 1);
while(x % i == 0)
x /= i;
}
}
if(x > 1)
ans = ans / x * (x - 1);
return ans ;
}
ll Mul(ll a,ll b,ll mod_val)
{
ll ans = 0;
ll t = a %mod_val;
while(b)
{
if(b&1)
{
ans = (ans + t) % mod_val;
}
t = t * 2 % mod_val;
b >>= 1;
}
return ans;
}
ll pow_mod(ll x,ll n,ll mod_val)
{
ll t = x;
ll ans = 1;
while(n)
{
if(n&1)
{
ans = Mul(ans,t,mod_val);
}
t = Mul(t,t,mod_val);
n >>= 1;
}
return ans ;
}
int main()
{
ll n;
// cout << euler(5) << endl;
// for(ll i = 1; i <= 10; i ++)
// cout << euler(i)<< " ";
while( ~ scanf("%I64d",&n) )
{
if(n % 2 == 0 || n == 1)
{
cout<< "2^? mod "<< n << " = 1" << endl;
continue;
}
ll m = euler(n);
// cout << m << endl;
ll ans = 10e18;
for(ll i = 1; i * i <= m; i ++)
{
if(m % i == 0)
{
if(pow_mod(2,i,n) == 1)
ans = min(ans,i);
if(pow_mod(2,m/i,n) == 1)
ans = min(ans,m/i);
}
}
cout<< "2^"<< ans << " mod " << n << " = 1" << endl;
}
return 0;
}