poj3696 The Luckiest number[欧拉定理]
注意到$L|\frac{8(10^x-1)}{9}$等价于$9L|8(10^x-1)$,这个等价转化一定要记住!(是可以证两者互为充要条件的)
于是整理后有$\frac{9L}{gcd(L,8)}|(10^x-1)$。
转化为同余方程来解决。
$10^x \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$
注意先排除无解情况。也就是说,10和模数必须互质。
若gcd含$2$或者$5$,则肯定无解,很显然。
然后互质前提下发现$\varphi(\frac{9L}{gcd(L,8)})$一定是一个解。(欧拉定理)
于是解的范围被我们明确为了$(0,\varphi(\frac{9L}{gcd(L,8)})]$。
尝试随便找一个数$x$假设$10^x \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$。
若模数$=qx+r$,$r$是小于等于$x$的一个余数
然后发现$10^{qx} \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$,
又$10^{qx+r} \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$。
则$10^r \equiv 1 \pmod{\frac{9L}{gcd(L,8)}}$。
这个说明这个$x$必须是$\varphi(\frac{9L}{gcd(L,8)})$的约数才有可能是解,否则会有更小的解$r$。
于是乎查找范围进一步被缩小为根号个。于是就可以枚举约数检验了。
这题可以使用特殊的快速乘。(现学的)
UPD:当然直接上BSGS也可以。当时不会。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define dbg(x) cerr << #x << " = " << x <<endl 7 using namespace std; 8 typedef long long ll; 9 typedef double db; 10 typedef pair<int,int> pii; 11 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 12 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;} 14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;} 16 template<typename T>inline T read(T&x){ 17 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 18 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 19 } 20 ll L,p,phi,tmp,ans; 21 int T; 22 inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} 23 inline void euler(){ 24 tmp=phi=p; 25 for(register ll i=2;i*i<=tmp;++i)if(tmp%i==0){ 26 phi=phi/i*(i-1); 27 while(tmp%i==0)tmp/=i; 28 } 29 if(tmp>1)phi=phi/tmp*(tmp-1); 30 } 31 inline ll mul(ll x,ll y){ 32 ll X=x*(y>>25)%p*(1<<25)%p; 33 ll Y=x*(y&((1<<25)-1))%p; 34 return (X+Y)%p; 35 } 36 //inline ll mul(ll a,ll b,ll mod){ 37 // return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod; 38 //} 39 inline ll fpow(ll x,ll k){ll ret=1;for(;k;k>>=1,x=mul(x,x))if(k&1)ret=mul(ret,x);return ret;} 40 41 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout); 42 while(read(L)){ 43 p=9*L/gcd(L,8); 44 if(p%2==0||p%5==0){printf("Case %d: 0\n",++T);continue;} 45 euler();ans=1e15; 46 for(register ll i=1;i*i<=phi;++i)if(phi%i==0){ 47 if(fpow(10%p,i)==1){ans=i;break;} 48 if(fpow(10%p,phi/i)==1)MIN(ans,phi/i); 49 } 50 printf("Case %d: %lld\n",++T,ans); 51 } 52 return 0; 53 }