1.题目链接。题目大意:给一个L,问存不存在一个数,这个数的数位上全是8并且整除L。如果存在,输出这个数的位数,否则输出0.
2.分析:开始看以为是一个水题,直接暴力枚举ll范围内的所有数据,然后发现不行。仔细分析应该时这样做。
我们知道对于所有的数位上全是A的数其实可以这样写:.那么全是8的数据通项公式就是:.这个数据能够整除L。写成等式就是:.下面来推导这个式子。
证明过程:
然后我们两边同时除以gcd(8,L)并且整理得到:
然后,整理到这里,我们就需要知道一些很重要的知识了,关于高次同余理论中,有两个很重要的结论:
这个方程并不总是有解的,只有在gcd(a,m)=1的时候,才有解。gcd(a,m)不等于1的时候无解。并且在有解的情况下,若存在x0满足上式,那么x0一定整除phi(m).其实这一点很好理解,从欧拉定理就可以看出来。就不再证明了。
知道了这些,这道题也就基本解决了。我们假设:m=9*L/gcd(8,L)的。那么我们只需要判断gcd(10,m)==1?,如果是的,我们就枚举phi(m)的因子,遍历输出最小的即可。当然了,在验证过程我们是需要使用快速幂的,但是因为快速幂在乘的时候会爆ll,所以采用快速乘+快速幂的形式即可。代码如下:
#include<iostream>
#include<cmath>
#include<stdio.h>
#include<cstdio>
#include<algorithm>
#include<vector>
#pragma warning(disable:4996)
using namespace std;
#define ll long long
vector<ll>vec;
ll gcd(ll a, ll b) {
return b ? gcd(b, a%b) : a;
}
ll phi(ll n)
{
ll res= n;
for (int i = 2; i*i<=n; i++)
{
if (n % i == 0)
{
res = res - res / i;
while (n%i == 0)n /= i;
}
}
if (n > 1)res = res - res / n;
return res;
}
ll qmul(ll a, ll b, ll mod)
{
ll ans = 0;
while (b)
{
if (b & 1)
ans = (ans + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return ans;
}
ll qpow(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 main()
{
int cas = 0;
ll l, m;
while (scanf("%lld", &l) && l)
{
vec.clear();
if (l == 0)break;
m = 9 * l / gcd(8, l);
if (gcd(10, m) != 1)
{
printf("Case %d: %d\n", ++cas, 0);
continue;
}
ll ans = phi(m);
for (ll i = 1; i*i <= ans; i++)
{
if (ans%i == 0)
{
vec.push_back(i);
if (ans != i * i)
vec.push_back(ans / i);
}
}
sort(vec.begin(), vec.end());
ll i = 0;
for (i; i <vec.size(); i++)
{
if (qpow(10, vec[i], m) == 1)
{
break;
}
}
printf("Case %d: %lld\n", ++cas, vec[i]);
}
}