定理:
设gcd(a,m)=1,必有正整数x,使得a^x=1(mod m),且设满足等式的最小正整数为x0,必满足x0|phi(m).注意m>1.
否则如果gcd(a,m)!=1,则方程a^x=1(mod m)没有解。
典型题目:HDU1395,HDU3307,POJ3696
前面两题很简单,下面我们来分析POJ3696.
题意:求出由全8组成的数的最短长度,使得给定的L能整除它。
分析:先分析公式,可以发现一个全由A组成的数的表示形式为:,所以全8组成的数为:。
L能整除它,则有:,亦即:,则应该先约去8与9L的最大公约数。
因为8与9互素,所以实际上就是约去8与L的最大公约数。
所以进一步有:,然后就是上面的那个定理了。
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
typedef long long LL;
LL dp[1000005];
LL gcd(LL a,LL b)
{
return b? gcd(b,a%b):a;
}
LL phi(LL n)
{
LL rea=n,i;
for(i=2;i*i<=n;i++)
{
if(n%i==0)
{
rea=rea-rea/i;
while(n%i==0) n/=i;
}
}
if(n>1)
rea=rea-rea/n;
return rea;
}
LL multi(LL a,LL b,LL m)
{
LL ans=0;
while(b)
{
if(b&1)
{
ans=(ans+a)%m;
b--;
}
b>>=1;
a=(a+a)%m;
}
return ans;
}
LL quick_mod(LL a,LL b,LL m)
{
LL ans=1;
a%=m;
while(b)
{
if(b&1)
{
ans=multi(ans,a,m);
b--;
}
b>>=1;
a=multi(a,a,m);
}
return ans;
}
int main()
{
int k=1;
LL L,i,m;
while(cin>>L)
{
if(L==0) break;
printf("Case %d: ",k++);
m=9*L/gcd(8,L);
if(gcd(10,m)!=1)
{
puts("0");
continue;
}
LL ans=phi(m);
LL size=0;
for(i=1;i*i<=ans;i++)
{
if(ans%i==0)
{
dp[size++]=i;
if(ans!=i*i) dp[size++]=ans/i;
}
}
sort(dp,dp+size);
for(i=0;i<size;i++)
if(quick_mod(10,dp[i],m)==1) break;
cout<<dp[i]<<endl;
}
return 0;
}