最幸运的数字
题意:给一个数L,问至少多少个8连在一起组成的正整数是L的倍数。
思路:x个8一起组成的正整数可表示为8*(10^x-1)/9。然后满足L|8*(10^x-1)/9。等价于10^x=1(mod9*L/d),d=gcd(L,8)。
所以我们只需要枚举phi[9*L/d]的约数就行了,看能否满足。满足的那个约数就是答案。前提是10与9*L/d互质。
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<queue> #include<cmath> #define ll long long using namespace std; ll n; ll f[100010]; ll gcd(ll a, ll b) { return b?gcd(b,a%b):a; } ll eler(ll m) { ll res=m; for(ll i=2;i*i<=m;i++) { if (m%i==0) res=res/i*(i-1); while(m%i==0) m/=i; } if(m>1) res=res/m*(m-1); return res; } void find(ll x) { ll s=x; f[0]=0; for(ll i=2;i*i<=s;i++) if (!(x%i)) { f[++f[0]]=i; while(!(x%i)) x/=i; } if(x>1) f[++f[0]]=x; } bool check(ll x,ll mod) { ll res=1; ll h=10; while(x) { if(x&1) res=(res*h)%mod; h=(h*h)%mod; x>>=1; } return (res%mod)==1; } int main() { int k=0; while(~scanf("%lld",&n)) { if(n==0) break; ll d=gcd(n,8ll); ll m=eler(9*n/d); ll p=9*n/d; if(gcd(p,10ll)!=1){ printf("Case %d: %lld\n",++k,0ll); continue; } find(m); // printf("m:%lld\n",m); // printf("p:%lld\n",p); for(ll i=1;i<=f[0];i++) { // printf("f:%d\n",f[i]); while(1) { m/=f[i]; if(!check(m,p)) { m*=f[i]; break; } else { if(m%f[i]) { break; } } } } printf("Case %d: %lld\n",++k,m); } }