1. 程式人生 > 其它 >最幸運的數字

最幸運的數字

技術標籤:藍書演算法acm競賽

題目傳送門
根據題意

1 0 x − 1 9 ∗ 8 ≡ 0 ( m o d L ) \frac{10^x-1}{9}*8\equiv0\pmod{L} 910x180(modL)

( 1 0 x − 1 ) ∗ 8 ≡ 0 ( m o d 9 L ) (10^x-1)*8\equiv0\pmod{9L} (10x1)80(mod9L)

令d=gcd(8,L)

( 1 0 x − 1 ) ∗ 8 d ≡ 0 ( m o d 9 L d ) (10^x-1)*\frac{8}{d}\equiv0\pmod{\frac{9L}{d}} (10x1)d80(modd9

L)

那麼此時 8 d 和 9 L d \frac{8}{d}和\frac{9L}{d} d8d9L一定是互質的,所以** ( 1 0 x − 1 ) ≡ 0 ( m o d 9 L d ) (10^x-1)\equiv0\pmod{\frac{9L}{d}} (10x1)0(modd9L)**

**所以 1 0 x ≡ 1 ( m o d 9 L d ) 10^x\equiv1\pmod{\frac{9L}{d}} 10x1(modd9L)

假設p= 9 L d \frac{9L}{d} d9L,當p和10互質時, Φ ( p ) \Phi(p) Φ(p)為其中一個解

我們可以證明最小的整數解一定是 Φ ( p ) \Phi(p)

Φ(p)的約數

如果不是約數的話,那麼a= Φ ( p ) \Phi(p) Φ(p)+r,就會推出 1 0 r ≡ 1 ( m o d 9 L d ) 10^r\equiv1\pmod{\frac{9L}{d}} 10r1(modd9L)

與a是最小解矛盾

所以問題轉換為求 Φ ( p ) \Phi(p) Φ(p)的約數,再對約數進行檢查是否滿足 1 0 x ≡ 1 ( m o d 9 L d ) 10^x\equiv1\pmod{\frac{9L}{d}} 10x1(modd9L)

時間複雜度
1.求 9 L d \frac{9L}{d} d9L,複雜度為 O ( L ) O(\sqrt[]{L})

O(L )
2.求 Φ ( p ) \Phi(p) Φ(p)的以及約數為 O ( Φ ( p ) + p ) O(\sqrt[]{\Phi(p)}+\sqrt[]{p}) O(Φ(p) +p )
3.用龜速冪檢查O( l o g Φ ( p ) ∗ l o g Φ ( p ) log\Phi(p)*log\Phi(p) logΦ(p)logΦ(p))

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int cnt;

ll qmul(ll a,ll b,ll mod)   //龜速冪,因為mod可能超過1e9,導致a*a超過longlong的範圍 
{
	ll res=0;
	while(b)
	{
		if(b&1) res=(res+a)%mod;
		a=(a+a)%mod;
		b>>=1;
	}
	return res;
}
ll qmi(ll a,ll b,ll mod)
{
	ll res=1;
	while(b)
	{
		if(b&1) res=qmul(res,a,mod);
		a=qmul(a,a,mod);
		b>>=1;
	}
	return res;
}


int phi(ll x)
{
	ll res=x;
	for(ll i=2;i<=x/i;i++)
	  {
	  	if(x%i==0)
	  	  {
	  	  	res=res/i*(i-1);
	  	  	while(x%i==0) x/=i;
		  }
	  }
	if(x>1) res=res/x*(x-1);
	return res;
}

ll gcd(ll a,ll b)
{
	return b==0?a:gcd(b,a%b);
}

int main()
{
	ll l;
	while(scanf("%lld ",&l)&&l)
	  {
	  	cnt++;
	  	
	  	bool flag=false;
	  	
	  	ll mod=9*l/gcd(8*1ll,l);
	  	
	  	ll p=phi(mod);
	  	
	  	ll res=1e18;
	  	
	  	for(ll i=1;i<=p/i;i++)
	  	  {
	  	  	 if(p%i==0)
	  	  	   {
	  	  	   	 if(qmi(10,i,mod)==1) res=min(res,i);
	  	  	   	 if(i!=p/i&&qmi(10,p/i,mod)==1) res=min(res,p/i); 
			   }
		  }
		printf("Case %d: %lld\n",cnt,res==1e18?0:res); 
	   }   
	return 0; 
}