此题大意就是给出一个数x 问他是否能乘以某个数后变成另一个数,使得每位都是8,然后问这个数的长度
我们观察888....这种数,可以发现,一个数如果能乘以某个数变成他,因子中不能有5,并且最多有3个2.
那么我们就先把所有的2因子都去掉,下面就是看他是否能乘某个数变成111....这样的数了
而111.... =( 10^m - 1) / 9
并且111...要mod x =0
那么就是( 10^m - 1) / 9 % x = 0
因为( 10^m - 1)必然可以整除掉9。所以不妨将上面的式子转化一下
( 10^m - 1) %(9 * x)= 0
即10^m % (9 * x) = 1
好了 ,由于我们刚才已经干掉了2因子和5因子,所以10^m显然和(9 * x)是互质的
那么可以发现这和欧拉函数怎么这么像。
没错,如果令m = phi(9 * x) 这个式子一定成立
但是我们要求最小的m啊
那么就去找phi(x)的因子了,找其中最小的因子k使得10^k % (9 * x) = 1 因为1乘1还是1么,所以这么干是很合理的
还有一个需要注意的是
快速幂取模的时候很蛋疼 ,因为有某些数是超int的,也就导致两数相乘超了int64
这就需要把乘法特殊处理一下,类似于那种快速幂的做法
#include <iostream> #include <algorithm> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <queue> #include <map> #include <set> #define MAXN 111111 #define MAXM 555555 #define INF 1000000011 #define lch(x) x<<1 #define rch(x) x<<1|1 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define eps 1e-7 using namespace std; long long euler(long long n) { long long x = n; long long i; long long phi = n; for (i = 2LL; i * i <= x; i++) { if (x % i == 0) { phi = phi / i * (i - 1LL) ; while (x % i == 0) x /= i; } } if (x != 1LL) phi = phi / x * (x - 1LL); return phi; } long long multi(long long a, long long b, long long c) { long long ret=0; while(b) { if(b&1) { ret+=a; if(ret>=c) ret-=c; } a+=a; if(a>=c) a-=c; b>>=1; } return ret; } long long fastmod(long long a, long long b, long long c)//a^b mod c { long long ret = 1; a %= c; for (; b; b >>= 1, a = multi(a, a, c)) if (b & 1) ret = multi(ret, a, c); return ret; } int main() { int cas = 0; long long n; while(scanf("%I64d", &n) != EOF && n) { int k = 0; while(n % 2 == 0) { n /= 2; k++; } if(k > 3 || n % 5 == 0) { printf("Case %d: 0\n", ++cas); continue; } n = n * 9LL; long long len = euler(n); long long ans = 100000000000LL; for(long long i = 1LL; i * i <= len; i++) { if(len % i == 0) { long long f = len / i; if(fastmod(10LL, i, n) == 1LL) ans = min(ans, i); if(fastmod(10LL, f, n) == 1LL) ans = min(ans, f); } } if(ans == 100000000000LL) ans = 0; printf("Case %d: %I64d\n", ++cas, ans); } return 0; }